On 8/22/23 08:58, Ales Musil wrote:
> On Thu, Aug 10, 2023 at 2:45 PM Dumitru Ceara <dce...@redhat.com> wrote:
> 
>> It's similar to the processing we do for address sets.  There's a bit
>> more mechanics involved due to the fact that we need to split NB port
>> groups per datapath.
>>
>> We currently only partially implement incremental processing of
>> port_group changes in the lflow node.  That is, we deal with the case
>> when the sets of "switches per port group" doesn't change.  In that
>> specific case ACL lflows don't need to be reprocessed.
>>
>> In a synthetic benchmark that created (in this order):
>> - 500 switches
>> - 2000 port groups
>> - 4 ACLs per port group
>> - 10000 ports distributed equally between the switches and port groups
>>
>> we measured the following ovn-northd CPU usage:
>>
>>   +-------------------------+------------+--------------------+
>>   | Incremental processing? | --wait=sb? | northd avg cpu (%) |
>>   +-------------------------+------------+--------------------+
>>   |           N             |     Y      |        84.2        |
>>   +-------------------------+------------+--------------------+
>>   |           Y             |     Y      |        41.5        |
>>   +-------------------------+------------+--------------------+
>>   |           N             |     N      |        93.2        |
>>   +-------------------------+------------+--------------------+
>>   |           Y             |     N      |        53.6        |
>>   +-------------------------+------------+--------------------+
>>
>> where '--wait=sb' set to 'Y'  means the benchmark was waiting for the
>> port and port group operations to be propagated to the Southbound DB
>> before continuing to the next operation.
>>
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2228162
>> Signed-off-by: Dumitru Ceara <dce...@redhat.com>
>> ---
>>
> 
> Hi Dumitru,
> 
> I have a couple of comments down below.
> 

Hi Ales,

Thanks for the review!

[..]

>>  static struct ls_port_group_record *
>>  ls_port_group_record_add(struct ls_port_group *ls_pg,
>>                           const struct nbrec_port_group *nb_pg,
>>                           const char *port_name)
>>  {
>> -    struct ls_port_group_record *ls_pg_rec = NULL;
>> +    struct ls_port_group_record *ls_pg_rec =
>> +        ls_port_group_record_find(ls_pg, nb_pg);
>>      size_t hash = uuid_hash(&nb_pg->header_.uuid);
>>
>> -    HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, &ls_pg->nb_pgs) {
>> -        if (ls_pg_rec->nb_pg == nb_pg) {
>> -            goto done;
>> -        }
>> +    if (!ls_pg_rec) {
>> +        ls_pg_rec = xzalloc(sizeof *ls_pg_rec);
>>
> 
> nit: No need for zeroed alloc as all the fields are immediately overwritten.
> 

Fair, I'll change it to xmalloc().

> +        *ls_pg_rec = (struct ls_port_group_record) {
>> +            .nb_pg = nb_pg,
>> +            .ports = SSET_INITIALIZER(&ls_pg_rec->ports),
>> +        };
>> +        hmap_insert(&ls_pg->nb_pgs, &ls_pg_rec->key_node, hash);
>>      }
>>
>> -    ls_pg_rec = xzalloc(sizeof *ls_pg_rec);
>> -    *ls_pg_rec = (struct ls_port_group_record) {
>> -        .nb_pg = nb_pg,
>> -        .ports = SSET_INITIALIZER(&ls_pg_rec->ports),
>> -    };
>> -    hmap_insert(&ls_pg->nb_pgs, &ls_pg_rec->key_node, hash);
>> -done:
>>      sset_add(&ls_pg_rec->ports, port_name);
>>      return ls_pg_rec;
>>  }
>>
>> +static struct ls_port_group_record *
>> +ls_port_group_record_find(struct ls_port_group *ls_pg,
>> +                          const struct nbrec_port_group *nb_pg)
>> +{
>> +    size_t hash = uuid_hash(&nb_pg->header_.uuid);
>> +    struct ls_port_group_record *ls_pg_rec;
>> +
>> +    HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, &ls_pg->nb_pgs) {
>> +        if (ls_pg_rec->nb_pg == nb_pg) {
>> +            return ls_pg_rec;
>> +        }
>> +    }
>> +    return NULL;
>> +}
>> +
>> +
>>  static void
>>  ls_port_group_record_destroy(struct ls_port_group *ls_pg,
>>                               struct ls_port_group_record *ls_pg_rec)
>> @@ -237,6 +372,71 @@ ls_port_group_record_destroy(struct ls_port_group
>> *ls_pg,
>>      }
>>  }
>>
>> +void
>> +port_group_to_ls_table_init(struct port_group_to_ls_table *table)
>> +{
>> +    *table = (struct port_group_to_ls_table) {
>> +        .entries = HMAP_INITIALIZER(&table->entries),
>> +    };
>> +}
>> +
>> +void
>> +port_group_to_ls_table_clear(struct port_group_to_ls_table *table)
>> +{
>> +    struct port_group_to_ls *pg_ls;
>> +    HMAP_FOR_EACH_SAFE (pg_ls, key_node, &table->entries) {
>> +        port_group_to_ls_destroy(table, pg_ls);
>> +    }
>> +}
>> +
>> +void
>> +port_group_to_ls_table_destroy(struct port_group_to_ls_table *table)
>> +{
>> +    port_group_to_ls_table_clear(table);
>> +    hmap_destroy(&table->entries);
>> +}
>> +
>> +struct port_group_to_ls *
>> +port_group_to_ls_table_find(const struct port_group_to_ls_table *table,
>> +                            const struct nbrec_port_group *nb_pg)
>> +{
>> +    struct port_group_to_ls *pg_ls;
>> +
>> +    HMAP_FOR_EACH_WITH_HASH (pg_ls, key_node,
>> uuid_hash(&nb_pg->header_.uuid),
>> +                             &table->entries) {
>>
> 
> We should move the uuid_hash call outside the loop.
> 
> 

As Han pointed out, that's not really needed.  I'll leave it as is.

Thanks,
Dumitru

>> +        if (nb_pg == pg_ls->nb_pg) {
>> +            return pg_ls;
>> +        }
>> +    }
>> +    return NULL;
>> +}
>> +
>> +static struct port_group_to_ls *
>> +port_group_to_ls_create(struct port_group_to_ls_table *table,
>> +                        const struct nbrec_port_group *nb_pg)
>> +{
>> +    struct port_group_to_ls *pg_ls = xmalloc(sizeof *pg_ls);
>> +
>> +    *pg_ls = (struct port_group_to_ls) {
>> +        .nb_pg = nb_pg,
>> +        .switches = HMAPX_INITIALIZER(&pg_ls->switches),
>> +    };
>> +    hmap_insert(&table->entries, &pg_ls->key_node,
>> +                uuid_hash(&nb_pg->header_.uuid));
>> +    return pg_ls;
>> +}
>> +
>> +static void
>> +port_group_to_ls_destroy(struct port_group_to_ls_table *table,
>> +                         struct port_group_to_ls *pg_ls)
>> +{
>> +    if (pg_ls) {
>> +        hmapx_destroy(&pg_ls->switches);
>> +        hmap_remove(&table->entries, &pg_ls->key_node);
>> +        free(pg_ls);
>> +    }
>> +}
>> +
>>  /* Incremental processing implementation. */
>>  static struct port_group_input
>>  port_group_get_input_data(struct engine_node *node)
>> @@ -259,6 +459,7 @@ en_port_group_init(struct engine_node *node OVS_UNUSED,
>>      struct port_group_data *pg_data = xmalloc(sizeof *pg_data);
>>
>>      ls_port_group_table_init(&pg_data->ls_port_groups);
>> +    port_group_to_ls_table_init(&pg_data->port_groups_to_ls);
>>      return pg_data;
>>  }
>>
>> @@ -268,6 +469,15 @@ en_port_group_cleanup(void *data_)
>>      struct port_group_data *data = data_;
>>
>>      ls_port_group_table_destroy(&data->ls_port_groups);
>> +    port_group_to_ls_table_destroy(&data->port_groups_to_ls);
>> +}
>> +
>> +void
>> +en_port_group_clear_tracked_data(void *data_)
>> +{
>> +    struct port_group_data *data = data_;
>> +
>> +    data->ls_port_groups_sets_unchanged = false;
>>  }
>>
>>  void
>> @@ -280,7 +490,10 @@ en_port_group_run(struct engine_node *node, void
>> *data_)
>>      stopwatch_start(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec());
>>
>>      ls_port_group_table_clear(&data->ls_port_groups);
>> +    port_group_to_ls_table_clear(&data->port_groups_to_ls);
>> +
>>      ls_port_group_table_build(&data->ls_port_groups,
>> +                              &data->port_groups_to_ls,
>>                                input_data.nbrec_port_group_table,
>>                                input_data.ls_ports);
>>
>> @@ -291,3 +504,133 @@ en_port_group_run(struct engine_node *node, void
>> *data_)
>>      stopwatch_stop(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec());
>>      engine_set_node_state(node, EN_UPDATED);
>>  }
>> +
>> +bool
>> +port_group_nb_port_group_handler(struct engine_node *node, void *data_)
>> +{
>> +    struct port_group_input input_data = port_group_get_input_data(node);
>> +    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 false;
>> +        }
>> +    }
>> +
>> +    struct hmapx updated_ls_port_groups =
>> +        HMAPX_INITIALIZER(&updated_ls_port_groups);
>> +
>> +    NBREC_PORT_GROUP_TABLE_FOR_EACH_TRACKED (nb_pg, nb_pg_table) {
>> +        /* Newly created port groups can't be incrementally processed;
>> +         * the rest yes. */
>> +        if (ls_port_group_process(&data->ls_port_groups,
>> +                                  &data->port_groups_to_ls,
>> +                                  input_data.ls_ports,
>> +                                  nb_pg, &updated_ls_port_groups)) {
>> +            success = false;
>> +            break;
>> +        }
>> +    }
>> +
>> +    /* If changes have been successfully processed incrementally then
>> 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 struct sbrec_port_group *sb_pg =
>> +                    sb_port_group_lookup_by_name(sbrec_port_group_by_name,
>> +                                                 ds_cstr(&sb_pg_name));
>> +                if (!sb_pg) {
>> +                    success = false;
>> +                    break;
>> +                }
>> +                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);
>> +    }
>> +
>> +    data->ls_port_groups_sets_unchanged = success;
>> +    engine_set_node_state(node, EN_UPDATED);
>> +    hmapx_destroy(&updated_ls_port_groups);
>> +    return success;
>> +}
>> +
>> +static void
>> +sb_port_group_apply_diff(const void *arg, const char *item, bool add)
>> +{
>> +    const struct sbrec_port_group *pg = arg;
>> +    if (add) {
>> +        sbrec_port_group_update_ports_addvalue(pg, item);
>> +    } else {
>> +        sbrec_port_group_update_ports_delvalue(pg, item);
>> +    }
>> +}
>> +
>> +static void
>> +update_sb_port_group(struct sorted_array *nb_ports,
>> +                     const struct sbrec_port_group *sb_pg)
>> +{
>> +    struct sorted_array sb_ports = sorted_array_from_dbrec(sb_pg, ports);
>> +    sorted_array_apply_diff(nb_ports, &sb_ports,
>> +                            sb_port_group_apply_diff, sb_pg);
>> +    sorted_array_destroy(&sb_ports);
>> +}
>> +
>> +static void
>> +sync_port_group(struct ovsdb_idl_txn *ovnsb_txn, const char *sb_pg_name,
>> +                struct sorted_array *ports,
>> +                struct shash *sb_port_groups)
>> +{
>> +    const struct sbrec_port_group *sb_port_group =
>> +        shash_find_and_delete(sb_port_groups, sb_pg_name);
>> +    if (!sb_port_group) {
>> +        sb_port_group = sbrec_port_group_insert(ovnsb_txn);
>> +        sbrec_port_group_set_name(sb_port_group, sb_pg_name);
>> +        sbrec_port_group_set_ports(sb_port_group, ports->arr, ports->n);
>> +    } else {
>> +        update_sb_port_group(ports, sb_port_group);
>> +    }
>> +}
>> +
>> +/* Finds and returns the port group set with the given 'name', or NULL
>> + * if no such port group exists. */
>> +static const struct sbrec_port_group *
>> +sb_port_group_lookup_by_name(struct ovsdb_idl_index
>> *sbrec_port_group_by_name,
>> +                             const char *name)
>> +{
>> +    struct sbrec_port_group *target = sbrec_port_group_index_init_row(
>> +        sbrec_port_group_by_name);
>> +    sbrec_port_group_index_set_name(target, name);
>> +
>> +    struct sbrec_port_group *retval = sbrec_port_group_index_find(
>> +        sbrec_port_group_by_name, target);
>> +
>> +    sbrec_port_group_index_destroy_row(target);
>> +    return retval;
>> +}
>> diff --git a/northd/en-port-group.h b/northd/en-port-group.h
>> index 5cbf6c6c4a..c3975f64ee 100644
>> --- a/northd/en-port-group.h
>> +++ b/northd/en-port-group.h
>> @@ -18,6 +18,7 @@
>>
>>  #include <stdint.h>
>>
>> +#include "lib/hmapx.h"
>>  #include "lib/inc-proc-eng.h"
>>  #include "lib/ovn-nb-idl.h"
>>  #include "lib/ovn-sb-idl.h"
>> @@ -54,9 +55,33 @@ struct ls_port_group *ls_port_group_table_find(
>>      const struct ls_port_group_table *,
>>      const struct nbrec_logical_switch *);
>>
>> -void ls_port_group_table_build(struct ls_port_group_table *ls_port_groups,
>> -                               const struct nbrec_port_group_table *,
>> -                               const struct hmap *ls_ports);
>> +/* Per port group map of datapaths with ports in the group. */
>> +struct port_group_to_ls_table {
>> +    struct hmap entries; /* Stores struct port_group_to_ls. */
>> +};
>> +
>> +struct port_group_to_ls {
>> +    struct hmap_node key_node; /* Index on 'pg->header_.uuid'. */
>> +
>> +    const struct nbrec_port_group *nb_pg;
>> +
>> +    /* Map of 'struct nbrec_logical_switch *' with ports in the group. */
>> +    struct hmapx switches;
>> +};
>> +
>> +void port_group_to_ls_table_init(struct port_group_to_ls_table *);
>> +void port_group_to_ls_table_clear(struct port_group_to_ls_table *);
>> +void port_group_to_ls_table_destroy(struct port_group_to_ls_table *);
>> +
>> +struct port_group_to_ls *port_group_to_ls_table_find(
>> +    const struct port_group_to_ls_table *,
>> +    const struct nbrec_port_group *);
>> +
>> +void ls_port_group_table_build(
>> +    struct ls_port_group_table *ls_port_groups,
>> +    struct port_group_to_ls_table *port_group_to_switches,
>> +    const struct nbrec_port_group_table *,
>> +    const struct hmap *ls_ports);
>>  void ls_port_group_table_sync(const struct ls_port_group_table
>> *ls_port_groups,
>>                                const struct sbrec_port_group_table *,
>>                                struct ovsdb_idl_txn *ovnsb_txn);
>> @@ -75,10 +100,15 @@ struct port_group_input {
>>
>>  struct port_group_data {
>>      struct ls_port_group_table ls_port_groups;
>> +    struct port_group_to_ls_table port_groups_to_ls;
>> +    bool ls_port_groups_sets_unchanged;
>>  };
>>
>>  void *en_port_group_init(struct engine_node *, struct engine_arg *);
>>  void en_port_group_cleanup(void *data);
>> +void en_port_group_clear_tracked_data(void *data);
>>  void en_port_group_run(struct engine_node *, void *data);
>>
>> +bool port_group_nb_port_group_handler(struct engine_node *, void *data);
>> +
>>  #endif /* EN_PORT_GROUP_H */
>> diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
>> index 6d5f9e8d16..bd598ba5e2 100644
>> --- a/northd/inc-proc-northd.c
>> +++ b/northd/inc-proc-northd.c
>> @@ -137,7 +137,7 @@ static ENGINE_NODE(mac_binding_aging_waker,
>> "mac_binding_aging_waker");
>>  static ENGINE_NODE(northd_output, "northd_output");
>>  static ENGINE_NODE(sync_to_sb, "sync_to_sb");
>>  static ENGINE_NODE(sync_to_sb_addr_set, "sync_to_sb_addr_set");
>> -static ENGINE_NODE(port_group, "port_group");
>> +static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(port_group, "port_group");
>>  static ENGINE_NODE(fdb_aging, "fdb_aging");
>>  static ENGINE_NODE(fdb_aging_waker, "fdb_aging_waker");
>>
>> @@ -193,7 +193,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>      engine_add_input(&en_lflow, &en_sb_multicast_group, NULL);
>>      engine_add_input(&en_lflow, &en_sb_igmp_group, NULL);
>>      engine_add_input(&en_lflow, &en_northd, lflow_northd_handler);
>> -    engine_add_input(&en_lflow, &en_port_group, NULL);
>> +    engine_add_input(&en_lflow, &en_port_group, lflow_port_group_handler);
>>
>>      engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set,
>>                       sync_to_sb_addr_set_nb_address_set_handler);
>> @@ -202,7 +202,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>      engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL);
>>      engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL);
>>
>> -    engine_add_input(&en_port_group, &en_nb_port_group, NULL);
>> +    engine_add_input(&en_port_group, &en_nb_port_group,
>> +                     port_group_nb_port_group_handler);
>>      engine_add_input(&en_port_group, &en_sb_port_group, NULL);
>>      /* No need for an explicit handler for northd changes.  Port changes
>>       * that affect port_groups trigger updates to the NB.Port_Group
>> @@ -287,6 +288,12 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
>>                                  "sbrec_address_set_by_name",
>>                                  sbrec_address_set_by_name);
>>
>> +    struct ovsdb_idl_index *sbrec_port_group_by_name
>> +        = ovsdb_idl_index_create1(sb->idl, &sbrec_port_group_col_name);
>> +    engine_ovsdb_node_add_index(&en_sb_port_group,
>> +                                "sbrec_port_group_by_name",
>> +                                sbrec_port_group_by_name);
>> +
>>      struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port
>>          = ovsdb_idl_index_create2(sb->idl, &sbrec_fdb_col_dp_key,
>>                                    &sbrec_fdb_col_port_key);
>> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
>> index 4fa1b039ea..44385d604c 100644
>> --- a/northd/ovn-northd.c
>> +++ b/northd/ovn-northd.c
>> @@ -836,6 +836,10 @@ main(int argc, char *argv[])
>>          ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
>>                               &sbrec_multicast_group_columns[i]);
>>      }
>> +    for (size_t i = 0; i < SBREC_PORT_GROUP_N_COLUMNS; i++) {
>> +        ovsdb_idl_omit_alert(ovnsb_idl_loop.idl,
>> +                             &sbrec_port_group_columns[i]);
>> +    }
>>
>>      unixctl_command_register("sb-connection-status", "", 0, 0,
>>                               ovn_conn_show, ovnsb_idl_loop.idl);
>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>> index 1a12513d7a..a04ba2b23f 100644
>> --- a/tests/ovn-northd.at
>> +++ b/tests/ovn-northd.at
>> @@ -8936,6 +8936,252 @@ AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE
>> inc-engine/show-stats sync_to_sb_a
>>  AT_CLEANUP
>>  ])
>>
>> +OVN_FOR_EACH_NORTHD_NO_HV([
>> +AT_SETUP([Port group incremental processing])
>> +ovn_start
>> +
>> +check ovn-nbctl ls-add sw1 \
>> +  -- lsp-add sw1 sw1.1     \
>> +  -- lsp-add sw1 sw1.2     \
>> +  -- lsp-add sw1 sw1.3     \
>> +  -- ls-add sw2            \
>> +  -- lsp-add sw2 sw2.1     \
>> +  -- lsp-add sw2 sw2.2     \
>> +  -- lsp-add sw2 sw2.3
>> +
>> +check ovn-nbctl --wait=sb sync
>> +sw1_key=$(fetch_column Datapath_Binding tunnel_key external_ids:name=sw1)
>> +sw2_key=$(fetch_column Datapath_Binding tunnel_key external_ids:name=sw2)
>> +
>> +check_acl_lflows() {
>> +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw1 | grep ls_in_acl_eval | grep
>> eth.src==41:41:41:41:41:41 -c], [ignore], [dnl
>> +$1
>> +])
>> +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw1 | grep ls_in_acl_eval | grep
>> eth.src==42:42:42:42:42:42 -c], [ignore], [dnl
>> +$2
>> +])
>> +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw2 | grep ls_in_acl_eval | grep
>> eth.src==41:41:41:41:41:41 -c], [ignore], [dnl
>> +$3
>> +])
>> +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw2 | grep ls_in_acl_eval | grep
>> eth.src==42:42:42:42:42:42 -c], [ignore], [dnl
>> +$4
>> +])
>> +}
>> +
>> +AS_BOX([Create new PG1 and PG2])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb -- pg-add pg1 -- pg-add 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 NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                0
>> +])
>> +dnl The port_group node recomputes every time a NB port group is
>> added/deleted.
>> +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                0
>> +])
>> +
>> +AS_BOX([Add ACLs on PG1 and PG2])
>> +check ovn-nbctl --wait=sb             \
>> +  -- 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
>> +
>> +AS_BOX([Add one port from the two switches to PG1])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb         \
>> +  -- pg-set-ports pg1 sw1.1 sw2.1
>> +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, it should handle nb_global
>> update
>> +dnl though, therefore "compute: 1".
>> +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                0
>> +])
>> +dnl Expect ACL1 on sw1 and sw2
>> +check_acl_lflows 1 0 1 0
>> +
>> +AS_BOX([Add one port from the two switches to PG2])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb \
>> +  -- 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"
>> +
>> +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 NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                0
>> +])
>> +dnl Expect both ACLs on sw1 and sw2
>> +check_acl_lflows 1 1 1 1
>> +
>> +AS_BOX([Add one more port from the two switches to PG1 and PG2])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb                     \
>> +  -- pg-set-ports pg1 sw1.1 sw2.1 sw1.3 sw2.3 \
>> +  -- pg-set-ports pg2 sw1.2 sw2.2 sw1.3 sw2.3
>> +check_column "sw1.1 sw1.3" sb:Port_Group ports name="${sw1_key}_pg1"
>> +check_column "sw2.1 sw2.3" sb:Port_Group ports name="${sw2_key}_pg1"
>> +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, it should handle nb_global
>> update
>> +dnl though, therefore "compute: 1".
>> +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                0
>> +])
>> +dnl Expect both ACLs on sw1 and sw2
>> +check_acl_lflows 1 1 1 1
>> +
>> +AS_BOX([Remove the last port from PG1 and PG2])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +check ovn-nbctl --wait=sb         \
>> +  -- 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"
>> +
>> +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 NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                0
>> +])
>> +dnl Expect both ACLs on sw1 and sw2
>> +check_acl_lflows 1 1 1 1
>> +
>> +AS_BOX([Remove the second port from PG1 and PG2])
>> +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>> +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"
>> +check_column "sw1.2" sb:Port_Group ports name="${sw1_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 NORTHD_TYPE inc-engine/show-stats
>> northd], [0], [dnl
>> +Node: northd
>> +- recompute:            0
>> +- compute:              1
>> +- abort:                0
>> +])
>> +dnl We did changed the set of switches a pg is applied to, there should be
>> +dnl a recompute.
>> +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats
>> port_group], [0], [dnl
>> +Node: port_group
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                0
>> +])
>> +dnl We did 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 NORTHD_TYPE inc-engine/show-stats
>> lflow], [0], [dnl
>> +Node: lflow
>> +- recompute:            1
>> +- compute:              0
>> +- abort:                0
>> +])
>> +dnl Expect both ACLs on sw1 and not on sw2.
>> +check_acl_lflows 1 1 0 0
>> +
>> +AT_CLEANUP
>> +])
>> +
>>  OVN_FOR_EACH_NORTHD([
>>  AT_SETUP([Check default drop])
>>  AT_KEYWORDS([drop])
>>
>>
> With that addressed:
> 
> Acked-by: Ales Musil <amu...@redhat.com>

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to