On Thu, Jul 31, 2025 at 3:06 AM Ales Musil <amu...@redhat.com> wrote:

>
>
> On Mon, Jul 28, 2025 at 5:42 PM Jacob Tanenbaum via dev <
> ovs-dev@openvswitch.org> wrote:
>
>> Several operations on Port Groups required a full database
>> recalculation.
>>
>> 1. Creating a new Port Group
>> 2. Deleting a Port Group
>> 3. adding a port from a switch with no other ports on a port group
>> 4. removing a port from a port group that is the last one from a
>>    specific switch
>>
>> Those four operations required a full database recalculation to ensure
>> that that the lflows from the ACLs and the southbound databases were
>> correctly populated. Instead reprocess only the relevant switches and
>> ACLs to avoid the cost of a full recalculation. This is done by having
>> the port_group_handler update the southbound database and pass the names
>> of the relevant switches to the ls_stateful_acl node.
>>
>> Tested using the ovn sandbox 3000 switches and 15000 ports, Creating a
>> port group with one ACL and one port
>> Without I-P improvements:
>>
>> Time spent on processing nb_cfg 2:
>>         ovn-northd delay before processing:     1ms
>>         ovn-northd completion:                  132ms
>>
>> With I-P improvements:
>>
>> Time spent on processing nb_cfg 5:
>>         ovn-northd delay before processing:     0ms
>>         ovn-northd completion:                  26ms
>>
>> Reported-at: https://issues.redhat.com/browse/FDP-758
>> Reported-by: Dumitru Ceara <dce...@redhat.com>
>> Signed-off-by: Jacob Tanenbaum <jtane...@redhat.com>
>>
>
> Hello Jacob,
>
> I have a couple of comments on top of what Lorenzo already wrote.
>
>
>>
>> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
>> index 63565ef80..ac8ebba16 100644
>> --- a/northd/en-lflow.c
>> +++ b/northd/en-lflow.c
>> @@ -157,22 +157,6 @@ lflow_northd_handler(struct engine_node *node,
>>      return EN_HANDLED_UPDATED;
>>  }
>>
>> -enum engine_input_handler_result
>> -lflow_port_group_handler(struct engine_node *node, void *data OVS_UNUSED)
>> -{
>> -    struct port_group_data *pg_data =
>> -        engine_get_input_data("port_group", node);
>> -
>> -    /* If the set of switches per port group didn't change then there's
>> no
>> -     * need to reprocess lflows.  Otherwise, there might be a need to
>> -     * add/delete port-group ACLs to/from switches. */
>> -    if (pg_data->ls_port_groups_sets_changed) {
>> -        return EN_UNHANDLED;
>> -    }
>> -
>> -    return EN_HANDLED_UPDATED;
>> -}
>> -
>>  enum engine_input_handler_result
>>  lflow_lr_stateful_handler(struct engine_node *node, void *data)
>>  {
>> diff --git a/northd/en-lflow.h b/northd/en-lflow.h
>> index d3c96c027..326be83f9 100644
>> --- a/northd/en-lflow.h
>> +++ b/northd/en-lflow.h
>> @@ -20,8 +20,6 @@ void *en_lflow_init(struct engine_node *node, struct
>> engine_arg *arg);
>>  void en_lflow_cleanup(void *data);
>>  enum engine_input_handler_result lflow_northd_handler(struct engine_node
>> *,
>>                                                        void *data);
>> -enum engine_input_handler_result lflow_port_group_handler(struct
>> engine_node *,
>> -                                                          void *data);
>>  enum engine_input_handler_result
>>  lflow_lr_stateful_handler(struct engine_node *, void *data);
>>  enum engine_input_handler_result
>> diff --git a/northd/en-ls-stateful.c b/northd/en-ls-stateful.c
>> index 6aec43415..7b2a3e065 100644
>> --- a/northd/en-ls-stateful.c
>> +++ b/northd/en-ls-stateful.c
>> @@ -159,11 +159,15 @@ ls_stateful_northd_handler(struct engine_node
>> *node, void *data_)
>>          struct ls_stateful_record *ls_stateful_rec =
>>              ls_stateful_table_find_(&data->table, od->nbs);
>>          ovs_assert(ls_stateful_rec);
>> -        ls_stateful_record_set_acls(ls_stateful_rec, od->nbs,
>> -                                    input_data.ls_port_groups);
>> -
>> -        /* Add the ls_stateful_rec to the tracking data. */
>> -        hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
>> +        /* Ensure that only one handler per engine run calls
>> +         * ls_stateful_record_set_acls on the same ls_stateful rec. */
>> +        if (!hmapx_contains(&data->trk_data.crupdated, ls_stateful_rec))
>> {
>>
>
>
> You can replace this with 'if (hmapx_add(..))', as hmapx_add will return a
> pointer
> if it's a new item, NULL otherwise.
>
>
>> +            ls_stateful_record_set_acls(ls_stateful_rec, od->nbs,
>> +                                        input_data.ls_port_groups);
>> +
>> +            /* Add the ls_stateful_rec to the tracking data. */
>> +            hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
>> +        }
>>      }
>>
>>      if (ls_stateful_has_tracked_data(&data->trk_data)) {
>> @@ -179,11 +183,24 @@ ls_stateful_port_group_handler(struct engine_node
>> *node, void *data_)
>>      struct port_group_data *pg_data =
>>          engine_get_input_data("port_group", node);
>>
>> -    if (pg_data->ls_port_groups_sets_changed) {
>> -        return EN_UNHANDLED;
>> +    struct ed_type_ls_stateful *data = data_;
>> +    struct hmapx_node *hmap_node;
>> +    HMAPX_FOR_EACH (hmap_node, &pg_data->ls_port_groups_sets_changed) {
>> +        const struct nbrec_logical_switch *nbs = hmap_node->data;
>> +        struct ls_stateful_record *ls_stateful_rec =
>> +            ls_stateful_table_find_(&data->table, nbs);
>> +        ovs_assert(ls_stateful_rec);
>> +        /* Ensure only one handler per engine run calls
>> +         * ls_stateful_record_set_acls on the same ls_stateful rec. */
>> +        if (!hmapx_contains(&data->trk_data.crupdated, ls_stateful_rec))
>> {
>>
>
> Same here with the hmapx_add.
>
>
>> +            ls_stateful_record_set_acls(ls_stateful_rec,
>> +                                        nbs,
>> +                                        &pg_data->ls_port_groups);
>> +            /* Add the ls_stateful_rec to the tracking data. */
>> +            hmapx_add(&data->trk_data.crupdated, ls_stateful_rec);
>> +        }
>>      }
>>
>> -    struct ed_type_ls_stateful *data = data_;
>>      if (ls_stateful_has_tracked_data(&data->trk_data)) {
>>          return EN_HANDLED_UPDATED;
>>      }
>> diff --git a/northd/en-port-group.c b/northd/en-port-group.c
>> index 4fc1a4f24..fd573d9df 100644
>> --- a/northd/en-port-group.c
>> +++ b/northd/en-port-group.c
>> @@ -33,18 +33,24 @@ static struct ls_port_group *ls_port_group_create(
>>  static void ls_port_group_destroy(struct ls_port_group_table *,
>>                                    struct ls_port_group *);
>>
>> -static bool ls_port_group_process(
>> +static void ls_port_group_process(
>>      struct ls_port_group_table *,
>>      struct port_group_ls_table *,
>> +    struct hmapx *,
>>      const struct hmap *ls_ports,
>>      const struct nbrec_port_group *,
>> -    struct hmapx *updated_ls_port_groups);
>> +    struct hmapx *updated_ls_port_groups,
>> +    struct sset *pruned_ls_port_group_recs);
>>
>>  static void ls_port_group_record_clear(
>>      struct ls_port_group_table *,
>>      struct port_group_ls_record *,
>>      struct hmapx *cleared_ls_port_groups);
>> -static bool ls_port_group_record_prune(struct ls_port_group *);
>> +
>> +static bool ls_port_group_record_prune(
>> +    struct ls_port_group *,
>> +    const struct nbrec_port_group *,
>> +    struct sset *);
>>
>>  static struct ls_port_group_record *ls_port_group_record_create(
>>      struct ls_port_group *,
>> @@ -118,8 +124,8 @@ ls_port_group_table_build(
>>  {
>>      const struct nbrec_port_group *nb_pg;
>>      NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_pg, pg_table) {
>> -        ls_port_group_process(ls_port_groups, port_group_lses,
>> -                              ls_ports, nb_pg, NULL);
>> +        ls_port_group_process(ls_port_groups, port_group_lses, NULL,
>> +                              ls_ports, nb_pg, NULL, NULL);
>>      }
>>  }
>>
>> @@ -206,20 +212,27 @@ ls_port_group_destroy(struct ls_port_group_table
>> *ls_port_groups,
>>      }
>>  }
>>
>> -/* Process a NB.Port_Group record and stores any updated ls_port_groups
>> - * in updated_ls_port_groups.  Returns true if a new ls_port_group had
>> - * to be created or destroyed.
>> +/* Process a NB.Port_Group record updated the ls_port_group_table and the
>> + * port_group_ls_table. Stores a few different updates
>> + *  1. Updated ls_port_groups are stored in updated_ls_port_groups so
>> the I-P
>> + *     can update the Southbound database
>> + *  2. If a port_groups switch set changes the switch is stored in
>> + *     ls_port_groups_sets_changed so that later I-P nodes can
>> recalculate
>> + *     lflows.
>> + *  3. If a port_group has a switch removed from it's switch set it is
>> stored
>> + *     in pruned_ls_port_group_recs so that the SB entry can be deleted.
>>   */
>> -static bool
>> +static void
>>  ls_port_group_process(struct ls_port_group_table *ls_port_groups,
>>                        struct port_group_ls_table *port_group_lses,
>> +                      struct hmapx *ls_port_groups_sets_changed,
>>                        const struct hmap *ls_ports,
>>                        const struct nbrec_port_group *nb_pg,
>> -                      struct hmapx *updated_ls_port_groups)
>> +                      struct hmapx *updated_ls_port_groups,
>> +                      struct sset *pruned_ls_port_group_recs)
>>  {
>>      struct hmapx cleared_ls_port_groups =
>>          HMAPX_INITIALIZER(&cleared_ls_port_groups);
>> -    bool ls_pg_rec_created = false;
>>
>>      struct port_group_ls_record *pg_ls =
>>          port_group_ls_table_find(port_group_lses, nb_pg);
>> @@ -233,6 +246,12 @@ ls_port_group_process(struct ls_port_group_table
>> *ls_port_groups,
>>      }
>>
>>      for (size_t i = 0; i < nb_pg->n_ports; i++) {
>> +        if (nbrec_port_group_is_deleted(nb_pg)) {
>> +            /* When a port group is deleted we don't need to
>> +             * updated the port group as the entry will be pruned
>> +             */
>> +            break;
>> +        }
>>          const char *port_name = nb_pg->ports[i]->name;
>>          const struct ovn_datapath *od =
>>              northd_get_datapath_for_port(ls_ports, port_name);
>> @@ -262,7 +281,10 @@ ls_port_group_process(struct ls_port_group_table
>> *ls_port_groups,
>>              ls_port_group_record_find(ls_pg, nb_pg);
>>          if (!ls_pg_rec) {
>>              ls_pg_rec = ls_port_group_record_create(ls_pg, nb_pg);
>> -            ls_pg_rec_created = true;
>> +            if (ls_port_groups_sets_changed) {
>> +                hmapx_add(ls_port_groups_sets_changed,
>> +                          CONST_CAST(struct nbrec_logical_switch *,
>> od->nbs));
>> +            }
>>          }
>>          sset_add(&ls_pg_rec->ports, port_name);
>>
>> @@ -273,13 +295,18 @@ ls_port_group_process(struct ls_port_group_table
>> *ls_port_groups,
>>          }
>>      }
>>
>> -    bool ls_pg_rec_destroyed = false;
>>      struct hmapx_node *node;
>>      HMAPX_FOR_EACH (node, &cleared_ls_port_groups) {
>>          struct ls_port_group *ls_pg = node->data;
>>
>> -        if (ls_port_group_record_prune(ls_pg)) {
>> -            ls_pg_rec_destroyed = true;
>> +        if (ls_port_group_record_prune(ls_pg,
>> +                                       nb_pg,
>> +                                       pruned_ls_port_group_recs)) {
>> +            if (ls_port_groups_sets_changed) {
>> +                hmapx_add(ls_port_groups_sets_changed,
>> +                    CONST_CAST(struct nbrec_logical_switch
>> *,ls_pg->nbs));
>> +                hmapx_find_and_delete(&pg_ls->switches, ls_pg->nbs);
>
>
>
> Shouldn't this be outside the second if? It feels like it should be part
> of the 'ls_port_group_record_prune()' TBH.
>

I can move the hmapx_find_and_delete() outside of the second if, but I am
not sure if it should be inside ls_port_group_record_prune(). There are two
different structs that are cleaned up `struct ls_port_group_record` and
`struct port_group_ls_record`. They hold the same information but in a
different way. So the ls_port_group_record_prune() removes a
ls_port_group_record from the ls_port_group_table and the
hmapx_find_and_delete() removes a switch from a port_group_ls_record. If
you feel strongly that the two operations should be combined should the
function name change? something like reconcile_port_group_tables()?


>
> +            }
>>          }
>>
>>          if (hmap_is_empty(&ls_pg->nb_pgs)) {
>> @@ -287,8 +314,6 @@ ls_port_group_process(struct ls_port_group_table
>> *ls_port_groups,
>>          }
>>      }
>>      hmapx_destroy(&cleared_ls_port_groups);
>> -
>> -    return ls_pg_rec_created || ls_pg_rec_destroyed;
>>  }
>>
>>  /* Destroys all the struct ls_port_group_record that might be associated
>> to
>> @@ -320,17 +345,27 @@ ls_port_group_record_clear(struct
>> ls_port_group_table *ls_to_port_groups,
>>  }
>>
>>  static bool
>> -ls_port_group_record_prune(struct ls_port_group *ls_pg)
>> +ls_port_group_record_prune(struct ls_port_group *ls_pg,
>> +                           const struct nbrec_port_group *nb_pg,
>> +                           struct sset *pruned_ls_pg_rec)
>>  {
>>      struct ls_port_group_record *ls_pg_rec;
>>      bool records_pruned = false;
>>
>> -    HMAP_FOR_EACH_SAFE (ls_pg_rec, key_node, &ls_pg->nb_pgs) {
>> -        if (sset_is_empty(&ls_pg_rec->ports)) {
>> -            ls_port_group_record_destroy(ls_pg, ls_pg_rec);
>> -            records_pruned = true;
>> +    struct ds sb_pg_name = DS_EMPTY_INITIALIZER;
>> +    ls_pg_rec = ls_port_group_record_find(ls_pg, nb_pg);
>> +    if (sset_is_empty(&ls_pg_rec->ports) ||
>> +        nbrec_port_group_is_deleted(ls_pg_rec->nb_pg)) {
>> +        if (pruned_ls_pg_rec) {
>>
> +            get_sb_port_group_name(ls_pg_rec->nb_pg->name,
>> +                                   ls_pg->sb_datapath_key,
>> +                                   &sb_pg_name);
>> +            sset_add(pruned_ls_pg_rec, ds_cstr(&sb_pg_name));
>>          }
>> +        ls_port_group_record_destroy(ls_pg, ls_pg_rec);
>> +        records_pruned = true;
>>      }
>> +    ds_destroy(&sb_pg_name);
>>      return records_pruned;
>>  }
>>
>> @@ -460,6 +495,10 @@ en_port_group_init(struct engine_node *node
>> OVS_UNUSED,
>>                     struct engine_arg *arg OVS_UNUSED)
>>  {
>>      struct port_group_data *pg_data = xmalloc(sizeof *pg_data);
>> +    *pg_data = (struct port_group_data) {
>> +        .ls_port_groups_sets_changed =
>> +            HMAPX_INITIALIZER(&pg_data->ls_port_groups_sets_changed),
>> +    };
>>
>>      ls_port_group_table_init(&pg_data->ls_port_groups);
>>      port_group_ls_table_init(&pg_data->port_groups_lses);
>> @@ -473,6 +512,7 @@ en_port_group_cleanup(void *data_)
>>
>>      ls_port_group_table_destroy(&data->ls_port_groups);
>>      port_group_ls_table_destroy(&data->port_groups_lses);
>> +    hmapx_destroy(&data->ls_port_groups_sets_changed);
>>  }
>>
>>  void
>> @@ -480,7 +520,7 @@ en_port_group_clear_tracked_data(void *data_)
>>  {
>>      struct port_group_data *data = data_;
>>
>> -    data->ls_port_groups_sets_changed = true;
>> +    hmapx_clear(&data->ls_port_groups_sets_changed);
>>  }
>>
>>  enum engine_node_state
>> @@ -514,73 +554,71 @@ port_group_nb_port_group_handler(struct engine_node
>> *node, void *data_)
>>      struct port_group_input input_data = port_group_get_input_data(node);
>>      const struct engine_context *eng_ctx = engine_get_context();
>>      struct port_group_data *data = data_;
>> -    bool success = true;
>>
>>      const struct nbrec_port_group_table *nb_pg_table =
>>          EN_OVSDB_GET(engine_get_input("NB_port_group", node));
>>      const struct nbrec_port_group *nb_pg;
>>
>> -    /* Return false if a port group is created or deleted.
>> -     * Handle I-P for only updated port groups. */
>> -    NBREC_PORT_GROUP_TABLE_FOR_EACH_TRACKED (nb_pg, nb_pg_table) {
>> -        if (nbrec_port_group_is_new(nb_pg) ||
>> -                nbrec_port_group_is_deleted(nb_pg)) {
>> -            return EN_UNHANDLED;
>> -        }
>> -    }
>> -
>>      struct hmapx updated_ls_port_groups =
>>          HMAPX_INITIALIZER(&updated_ls_port_groups);
>>
>> +    struct sset stale_sb_port_groups =
>> SSET_INITIALIZER(&stale_sb_port_groups);
>>      NBREC_PORT_GROUP_TABLE_FOR_EACH_TRACKED (nb_pg, nb_pg_table) {
>> -        if (ls_port_group_process(&data->ls_port_groups,
>> -                                  &data->port_groups_lses,
>> -                                  input_data.ls_ports,
>> -                                  nb_pg, &updated_ls_port_groups)) {
>> -            success = false;
>> -            break;
>> +        ls_port_group_process(&data->ls_port_groups,
>> +                              &data->port_groups_lses,
>> +                              &data->ls_port_groups_sets_changed,
>> +                              input_data.ls_ports,
>> +                              nb_pg, &updated_ls_port_groups,
>> +                              &stale_sb_port_groups);
>> +
>>          }
>> -    }
>>
>> -    /* If changes have been successfully processed incrementally then
>> update
>> +    /* Changes have been successfully processed incrementally now update
>>       * the SB too. */
>> -    if (success) {
>> -        struct ovsdb_idl_index *sbrec_port_group_by_name =
>> -            engine_ovsdb_node_get_index(
>> -                    engine_get_input("SB_port_group", node),
>> -                    "sbrec_port_group_by_name");
>> -        struct ds sb_pg_name = DS_EMPTY_INITIALIZER;
>> -
>> -        struct hmapx_node *updated_node;
>> -        HMAPX_FOR_EACH (updated_node, &updated_ls_port_groups) {
>> -            const struct ls_port_group *ls_pg = updated_node->data;
>> -            struct ls_port_group_record *ls_pg_rec;
>> -
>> -            HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) {
>> -                get_sb_port_group_name(ls_pg_rec->nb_pg->name,
>> -                                        ls_pg->sb_datapath_key,
>> -                                        &sb_pg_name);
>> -
>> -                const char *sb_pg_name_cstr = ds_cstr(&sb_pg_name);
>> -                const struct sbrec_port_group *sb_pg =
>> -
>> sb_port_group_lookup_by_name(sbrec_port_group_by_name,
>> -                                                 sb_pg_name_cstr);
>> -                if (!sb_pg) {
>> -                    sb_pg = create_sb_port_group(eng_ctx->ovnsb_idl_txn,
>> -                                                 sb_pg_name_cstr);
>> -                }
>> -                struct sorted_array nb_ports =
>> -                    sorted_array_from_sset(&ls_pg_rec->ports);
>> -                update_sb_port_group(&nb_ports, sb_pg);
>> -                sorted_array_destroy(&nb_ports);
>> +    struct ovsdb_idl_index *sbrec_port_group_by_name =
>> +        engine_ovsdb_node_get_index(
>> +                engine_get_input("SB_port_group", node),
>> +                "sbrec_port_group_by_name");
>> +    struct ds sb_pg_name = DS_EMPTY_INITIALIZER;
>> +
>> +    struct hmapx_node *updated_node;
>> +    HMAPX_FOR_EACH (updated_node, &updated_ls_port_groups) {
>> +        const struct ls_port_group *ls_pg = updated_node->data;
>> +        struct ls_port_group_record *ls_pg_rec;
>> +
>> +        HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) {
>> +            get_sb_port_group_name(ls_pg_rec->nb_pg->name,
>> +                                   ls_pg->sb_datapath_key,
>> +                                   &sb_pg_name);
>> +
>> +            const char *sb_pg_name_cstr = ds_cstr(&sb_pg_name);
>> +            const struct sbrec_port_group *sb_pg =
>> +                sb_port_group_lookup_by_name(sbrec_port_group_by_name,
>> +                                             sb_pg_name_cstr);
>> +            if (!sb_pg) {
>> +                sb_pg = create_sb_port_group(eng_ctx->ovnsb_idl_txn,
>> +                                             sb_pg_name_cstr);
>>              }
>> +            struct sorted_array nb_ports =
>> +                sorted_array_from_sset(&ls_pg_rec->ports);
>> +            update_sb_port_group(&nb_ports, sb_pg);
>> +            sorted_array_destroy(&nb_ports);
>>          }
>> -        ds_destroy(&sb_pg_name);
>>      }
>> +    ds_destroy(&sb_pg_name);
>> +
>> +    const char *stale_sb_port_group_name;
>> +    SSET_FOR_EACH (stale_sb_port_group_name, &stale_sb_port_groups) {
>> +        const struct sbrec_port_group *sb_pg =
>> +            sb_port_group_lookup_by_name(sbrec_port_group_by_name,
>> +                                         stale_sb_port_group_name);
>> +            sbrec_port_group_delete(sb_pg);
>> +    }
>> +    sset_destroy(&stale_sb_port_groups);
>> +
>>
>> -    data->ls_port_groups_sets_changed = !success;
>>      hmapx_destroy(&updated_ls_port_groups);
>> -    return success ? EN_HANDLED_UPDATED : EN_UNHANDLED;
>> +    return EN_HANDLED_UPDATED;
>>  }
>>
>>  static void
>> diff --git a/northd/en-port-group.h b/northd/en-port-group.h
>> index 8dcc950da..f07f118aa 100644
>> --- a/northd/en-port-group.h
>> +++ b/northd/en-port-group.h
>> @@ -104,7 +104,7 @@ struct port_group_input {
>>  struct port_group_data {
>>      struct ls_port_group_table ls_port_groups;
>>      struct port_group_ls_table port_groups_lses;
>> -    bool ls_port_groups_sets_changed;
>> +    struct hmapx ls_port_groups_sets_changed;
>>  };
>>
>>  void *en_port_group_init(struct engine_node *, struct engine_arg *);
>> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
>> index d43bfc16c..fc4ae58f8 100644
>> --- a/northd/inc-proc-northd.c
>> +++ b/northd/inc-proc-northd.c
>> @@ -348,7 +348,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>      engine_add_input(&en_lflow, &en_sampling_app, NULL);
>>
>>      engine_add_input(&en_lflow, &en_northd, lflow_northd_handler);
>> -    engine_add_input(&en_lflow, &en_port_group,
>> lflow_port_group_handler);
>> +    engine_add_input(&en_lflow, &en_port_group, engine_noop_handler);
>>
>
> Please add a comment explaining why lflow doesn't
> need to handle PG changes anymore.
>
>
>>      engine_add_input(&en_lflow, &en_lr_stateful,
>> lflow_lr_stateful_handler);
>>      engine_add_input(&en_lflow, &en_ls_stateful,
>> lflow_ls_stateful_handler);
>>      engine_add_input(&en_lflow, &en_multicast_igmp,
>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>> index 5e0747fcc..61d00e576 100644
>> --- a/tests/ovn-northd.at
>> +++ b/tests/ovn-northd.at
>> @@ -10100,27 +10100,11 @@ AS_BOX([Create new PG1 and PG2])
>>  check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>>  check ovn-nbctl --wait=sb -- pg-add pg1 -- pg-add pg2
>>  dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl The port_group node recomputes every time a NB port group is
>> added/deleted.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl The port_group node is an input for the lflow node.  Port_group
>> -dnl recompute/compute triggers lflow recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> +check_engine_stats northd norecompute compute
>> +dnl The port_group node does not recompute when a NB port group is
>> added/deleted.
>> +check_engine_stats port_group norecompute compute
>> +dnl The Port group recompute/compute should not trigger an lflow
>> recompute.
>> +check_engine_stats lflow norecompute compute
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>
>>  AS_BOX([Add ACLs on PG1 and PG2])
>> @@ -10137,28 +10121,15 @@ check_column "sw1.1" sb:Port_Group ports
>> name="${sw1_key}_pg1"
>>  check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1"
>>
>>  dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl The port_group node recomputes also every time a port from a new
>> switch
>> -dnl is added to the group.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl The port_group node is an input for the lflow node.  Port_group
>> -dnl recompute/compute triggers lflow recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> +check_engine_stats northd norecompute compute
>> +dnl The port_group node does not recompute when a new switch is added to
>> the
>> +dnl group
>> +check_engine_stats port_group norecompute compute
>> +dnl The port_group node is an input for the ls_statful node.  Port_group
>> +dnl should not trigger a recompute.
>> +check_engine_stats ls_stateful norecompute compute
>> +dnl Port_Group compute/recompute should not trigger an lflow recompute.
>> +check_engine_stats lflow norecompute compute
>>  dnl Expect ACL1 on sw1 and sw2
>>  check_acl_lflows 1 0 1 0
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> @@ -10173,29 +10144,16 @@ check_column "sw1.2" sb:Port_Group ports
>> name="${sw1_key}_pg2"
>>  check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2"
>>
>>  dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl The port_group node recomputes also every time a port from a new
>> switch
>> +check_engine_stats northd norecompute compute
>> +dnl The port_group node should not recompute when a  port from a new
>> switch
>>
>
> nit: Extra space.
>
>
>>  dnl is added to the group.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl The port_group node is an input for the lflow node.  Port_group
>> -dnl recompute/compute triggers lflow recompute (for ACLs).
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl Expect both ACLs on sw1 and sw2
>> +check_engine_stats port_group norecompute compute
>> +dnl The port_group node is an input for the ls_statful node.  Port_group
>> +dnl should not trigger a recompute
>> +check_engine_stats ls_stateful norecompute compute
>> +dnl Port_Group compute/recompute should not trigger an lflow recompute.
>> +check_engine_stats lflow norecompute compute
>> +dnl Expect both ACLs on sw1 and sw2.
>>  check_acl_lflows 1 1 1 1
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>
>> @@ -10210,29 +10168,11 @@ check_column "sw1.2 sw1.3" sb:Port_Group ports
>> name="${sw1_key}_pg2"
>>  check_column "sw2.2 sw2.3" sb:Port_Group ports name="${sw2_key}_pg2"
>>
>>  dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We did not change the set of switches a pg is applied to, there
>> should be
>> -dnl no recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We did not change the set of switches a pg is applied to, there
>> should be
>> -dnl no recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl Expect both ACLs on sw1 and sw2
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +dnl Expect both ACLs on sw1 and sw2.
>>  check_acl_lflows 1 1 1 1
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>
>> @@ -10248,28 +10188,10 @@ check_column "sw2.2" sb:Port_Group ports
>> name="${sw2_key}_pg2"
>>
>>  dnl The northd node should not recompute, it should handle nb_global
>> update
>>  dnl though, therefore "compute: 1".
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We did not change the set of switches a pg is applied to, there
>> should be
>> -dnl no recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We did not change the set of switches a pg is applied to, there
>> should be
>> -dnl no recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>>  dnl Expect both ACLs on sw1 and sw2
>>  check_acl_lflows 1 1 1 1
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> @@ -10280,32 +10202,19 @@ check ovn-nbctl --wait=sb pg-set-ports pg2 sw1.2
>>  check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1"
>>  check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1"
>>  check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2"
>> +
>>  AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
>>  ])
>>
>>  dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be
>> +check_engine_stats northd norecompute compute
>> +dnl We changed the set of switches a pg is applied to, this should no
>> longer require
>>  dnl a recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be
>> -dnl a recompute (for ACLs).
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> +check_engine_stats port_group norecompute compute
>> +dnl There should be no recompute for ls_stateful
>> +check_engine_stats ls_stateful norecompute compute
>> +dnl No recompute should occur.
>> +check_engine_stats lflow norecompute compute
>>  dnl Expect both ACLs on sw1 and only the first one on sw2.
>>  check_acl_lflows 1 1 1 0
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> @@ -10320,29 +10229,11 @@ check_column "sw1.2" sb:Port_Group ports
>> name="${sw1_key}_pg2"
>>  AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
>>  ])
>>
>> -dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be
>> -dnl a recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be
>> -dnl a recompute (for ACLs).
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +
>>  dnl Expect both ACLs on sw1 and not on sw2.
>>  check_acl_lflows 1 1 0 0
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> @@ -10357,36 +10248,18 @@ check_column "sw2.1" sb:Port_Group ports
>> name="${sw2_key}_pg1"
>>  check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2"
>>  check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2"
>>
>> -dnl The northd node should not recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be a
>> -dnl recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be a
>> -dnl recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +
>>  dnl Expect both ACLs on sw1 and sw2
>>  check_acl_lflows 1 1 1 1
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>
>>  AS_BOX([Remove second port from both PGs])
>>  check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> -check ovn-nbctl --wait=sb         \
>> +check ovn-nbctl --wait=sb   \
>>    -- pg-set-ports pg1 sw1.1 \
>>    -- pg-set-ports pg2 sw1.2
>>  check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1"
>> @@ -10396,33 +10269,53 @@ check_column "sw1.2" sb:Port_Group ports
>> name="${sw1_key}_pg2"
>>  AT_CHECK([fetch_column sb:Port_Group ports name="${sw2_key}_pg2"], [0], [
>>  ])
>>
>> -dnl The northd node should not recompute,.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> northd], [0], [dnl
>> -Node: northd
>> -- recompute:            0
>> -- compute:              1
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be a
>> -dnl recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> port_group], [0], [dnl
>> -Node: port_group
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl We changed the set of switches a pg is applied to, there should be a
>> -dnl recompute.
>> -AT_CHECK([as northd ovn-appctl -t ovn-northd inc-engine/show-stats
>> lflow], [0], [dnl
>> -Node: lflow
>> -- recompute:            1
>> -- compute:              0
>> -- cancel:               0
>> -])
>> -dnl Expect both ACLs on sw1 and no ACLs on sw2
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +
>> +dnl Expect both ACLs sw1
>>  check_acl_lflows 1 1 0 0
>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>
>> +AS_BOX([Delete port groups PG1 and PG2])
>> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb   \
>> +    -- pg-del pg1           \
>> +    -- pg-del pg2
>> +
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +
>> +dnl Expect no ACLs on sw1 and no ACLs on sw2
>> +check_acl_lflows 0 0 0 0
>> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> +
>> +AS_BOX([Add PG1 and PG2 again setting ports and ACLs in one transaction])
>> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb                                        \
>> +    -- pg-add pg1                                                \
>> +    -- pg-add pg2                                                \
>> +    -- acl-add pg1 from-lport 1 eth.src==41:41:41:41:41:41 allow \
>> +    -- acl-add pg2 from-lport 1 eth.src==42:42:42:42:42:42 allow \
>> +    -- pg-set-ports pg1 sw1.1 sw2.1                              \
>> +    -- pg-set-ports pg2 sw1.2 sw2.2
>> +check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1"
>> +check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1"
>> +check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2"
>> +check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2"
>> +
>> +check_engine_stats northd norecompute compute
>> +check_engine_stats port_group norecompute compute
>> +check_engine_stats ls_stateful norecompute compute
>> +check_engine_stats lflow norecompute compute
>> +
>> +dnl Expect both ACLs on sw1 and sw2
>> +check_acl_lflows 1 1 1 1
>> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> +
>>  AT_CLEANUP
>>  ])
>>
>> --
>> 2.50.1
>>
>> _______________________________________________
>> dev mailing list
>> d...@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>>
> Thanks,
> Ales
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to