On 11/15/23 19:22, Numan Siddique wrote:
> On Wed, Nov 15, 2023 at 12:12 AM Han Zhou <[email protected]> wrote:
>>
>> On Thu, Oct 26, 2023 at 11:14 AM <[email protected]> wrote:
>>>
>>> From: Numan Siddique <[email protected]>
>>>
>>> northd engine tracking data now has the following tracking data
>>>   - changed ovn_ports (right now only changed logical switch ports are
>>>     tracked.)
>>>   - changed load balancers.
>>>
>>> This separation becomes easier to add lflow handling for these
>>> changes in lflow northd engine handler.  This patch doesn't
>>> handle the load balancer changes in lflow handler.  It will
>>> be handled in upcoming commits.
>>>
>>> Signed-off-by: Numan Siddique <[email protected]>
>>> ---

Hi Numan,

I have a couple of comments too below, nothing fundamental but
hopefully something that would simplify the code a bit.

Regards,
Dumitru

>>>  northd/en-lflow.c   |  11 +-
>>>  northd/en-northd.c  |  13 +-
>>>  northd/en-sync-sb.c |  10 +-
>>>  northd/northd.c     | 446 ++++++++++++++++++++++++--------------------
>>>  northd/northd.h     |  63 ++++---
>>>  tests/ovn-northd.at |  10 +-
>>>  6 files changed, 313 insertions(+), 240 deletions(-)
>>>
>>> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
>>> index 2b84fef0ef..96d03b7ada 100644
>>> --- a/northd/en-lflow.c
>>> +++ b/northd/en-lflow.c
>>> @@ -108,8 +108,8 @@ lflow_northd_handler(struct engine_node *node,
>>>          return false;
>>>      }
>>>
>>> -    /* Fall back to recompute if lb related data has changed. */
>>> -    if (northd_data->lb_changed) {
>>> +    /* Fall back to recompute if load balancers have changed. */
>>> +    if
>> (northd_has_lbs_in_tracked_data(&northd_data->trk_northd_changes)) {
>>>          return false;
>>>      }
>>>
>>> @@ -119,13 +119,14 @@ lflow_northd_handler(struct engine_node *node,
>>>      struct lflow_input lflow_input;
>>>      lflow_get_input_data(node, &lflow_input);
>>>
>>> -    if (!lflow_handle_northd_ls_changes(eng_ctx->ovnsb_idl_txn,
>>> -                                        &northd_data->tracked_ls_changes,
>>> -                                        &lflow_input,
>> &lflow_data->lflows)) {
>>> +    if (!lflow_handle_northd_port_changes(eng_ctx->ovnsb_idl_txn,
>>> +
>>  &northd_data->trk_northd_changes.trk_ovn_ports,
>>> +                                &lflow_input, &lflow_data->lflows)) {
>>>          return false;
>>>      }
>>>
>>>      engine_set_node_state(node, EN_UPDATED);
>>> +

Nit: unrelated?

>>>      return true;
>>>  }
>>>
>>> diff --git a/northd/en-northd.c b/northd/en-northd.c
>>> index aa0f20f0c2..96c2ce9f69 100644
>>> --- a/northd/en-northd.c
>>> +++ b/northd/en-northd.c
>>> @@ -230,15 +230,16 @@ northd_lb_data_handler(struct engine_node *node,
>> void *data)
>>>                                         &nd->ls_datapaths,
>>>                                         &nd->lr_datapaths,
>>>                                         &nd->lb_datapaths_map,
>>> -                                       &nd->lb_group_datapaths_map)) {
>>> +                                       &nd->lb_group_datapaths_map,
>>> +                                       &nd->trk_northd_changes)) {
>>>          return false;
>>>      }
>>>
>>> -    /* Indicate the depedendant engine nodes that load balancer/group
>>> -     * related data has changed (including association to logical
>>> -     * switch/router). */
>>> -    nd->lb_changed = true;
>>> -    engine_set_node_state(node, EN_UPDATED);
>>> +    if (northd_has_lbs_in_tracked_data(&nd->trk_northd_changes)) {
>>> +        nd->change_tracked = true;
>>> +        engine_set_node_state(node, EN_UPDATED);
>>> +    }
>>> +
>>>      return true;
>>>  }
>>>
>>> diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
>>> index 2ec3bf54f8..2540fcfb97 100644
>>> --- a/northd/en-sync-sb.c
>>> +++ b/northd/en-sync-sb.c
>>> @@ -236,7 +236,8 @@ sync_to_sb_lb_northd_handler(struct engine_node
>> *node, void *data OVS_UNUSED)
>>>  {
>>>      struct northd_data *nd = engine_get_input_data("northd", node);
>>>
>>> -    if (!nd->change_tracked || nd->lb_changed) {
>>> +    if (!nd->change_tracked ||
>>> +            northd_has_lbs_in_tracked_data(&nd->trk_northd_changes)) {
>>>          /* Return false if no tracking data or if lbs changed. */
>>>          return false;
>>>      }
>>> @@ -306,11 +307,14 @@ sync_to_sb_pb_northd_handler(struct engine_node
>> *node, void *data OVS_UNUSED)
>>>      }
>>>
>>>      struct northd_data *nd = engine_get_input_data("northd", node);
>>> -    if (!nd->change_tracked) {
>>> +    if (!nd->change_tracked ||
>>> +            northd_has_lbs_in_tracked_data(&nd->trk_northd_changes)) {
>>> +        /* Return false if no tracking data or if lbs changed. */
>>>          return false;
>>>      }
>>>
>>> -    if (!sync_pbs_for_northd_ls_changes(&nd->tracked_ls_changes)) {
>>> +    if (!sync_pbs_for_northd_changed_ovn_ports(
>>> +            &nd->trk_northd_changes.trk_ovn_ports)) {
>>>          return false;
>>>      }
>>>
>>> diff --git a/northd/northd.c b/northd/northd.c
>>> index f8b046d83e..df22a9c658 100644
>>> --- a/northd/northd.c
>>> +++ b/northd/northd.c
>>> @@ -4894,21 +4894,20 @@ sync_pbs(struct ovsdb_idl_txn *ovnsb_idl_txn,
>> struct hmap *ls_ports)
>>>  }
>>>
>>>  /* Sync the SB Port bindings for the added and updated logical switch
>> ports
>>> - *  of the tracked logical switches (from the northd engine node). */
>>> + * of the tracked northd engine data. */
>>>  bool
>>> -sync_pbs_for_northd_ls_changes(struct tracked_ls_changes *ls_changes)
>>> +sync_pbs_for_northd_changed_ovn_ports( struct tracked_ovn_ports
>> *trk_ovn_ports)
>>>  {
>>> -    struct ls_change *ls_change;
>>> -    LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
>>> -        struct ovn_port *op;
>>> -
>>> -        LIST_FOR_EACH (op, list, &ls_change->added_ports) {
>>> -            sync_pb_for_op(op);
>>> -        }
>>> +    struct hmapx_node *hmapx_node;
>>> +    struct ovn_port *op;
>>> +    HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->created) {
>>> +        op = hmapx_node->data;
>>> +        sync_pb_for_op(op);
>>> +    }
>>>
>>> -        LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
>>> -            sync_pb_for_op(op);
>>> -        }
>>> +    HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->updated) {
>>> +        op = hmapx_node->data;
>>> +        sync_pb_for_op(op);
>>>      }
>>>
>>>      return true;
>>> @@ -5110,34 +5109,95 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
>>>  }
>>>
>>>  static void
>>> -destroy_tracked_ls_change(struct ls_change *ls_change)
>>> +destroy_tracked_ovn_ports(struct tracked_ovn_ports *trk_ovn_ports)
>>>  {
>>> -    struct ovn_port *op;
>>> -    LIST_FOR_EACH (op, list, &ls_change->added_ports) {
>>> -        ovs_list_remove(&op->list);
>>> -    }
>>> -    LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
>>> -        ovs_list_remove(&op->list);
>>> +    struct hmapx_node *hmapx_node;
>>> +    HMAPX_FOR_EACH_SAFE (hmapx_node, &trk_ovn_ports->deleted) {
>>> +        ovn_port_destroy_orphan(hmapx_node->data);
>>> +        hmapx_delete(&trk_ovn_ports->deleted, hmapx_node);
>>>      }
>>> -    LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
>>> -        ovs_list_remove(&op->list);
>>> -        ovn_port_destroy_orphan(op);
>>> +
>>> +    hmapx_clear(&trk_ovn_ports->created);
>>> +    hmapx_clear(&trk_ovn_ports->updated);
>>> +}
>>> +
>>> +static void
>>> +destroy_tracked_lbs(struct tracked_lbs *trk_lbs)
>>> +{
>>> +    struct hmapx_node *hmapx_node;
>>> +    HMAPX_FOR_EACH_SAFE (hmapx_node, &trk_lbs->deleted) {
>>> +        ovn_lb_datapaths_destroy(hmapx_node->data);
>>> +        hmapx_delete(&trk_lbs->deleted, hmapx_node);
>>>      }
>>> +
>>> +    hmapx_clear(&trk_lbs->crupdated);
>>> +}
>>> +
>>> +static void
>>> +add_op_to_northd_tracked_ports(struct hmapx *tracked_ovn_ports,
>>> +                               struct ovn_port *op)
>>> +{
>>> +    hmapx_add(tracked_ovn_ports, op);
>>>  }
>>>
>>>  void
>>>  destroy_northd_data_tracked_changes(struct northd_data *nd)
>>>  {
>>> -    struct ls_change *ls_change;
>>> -    LIST_FOR_EACH_SAFE (ls_change, list_node,
>>> -                        &nd->tracked_ls_changes.updated) {
>>> -        destroy_tracked_ls_change(ls_change);
>>> -        ovs_list_remove(&ls_change->list_node);
>>> -        free(ls_change);
>>> -    }
>>> -
>>> +    struct northd_tracked_data *trk_changes = &nd->trk_northd_changes;
>>> +    destroy_tracked_ovn_ports(&trk_changes->trk_ovn_ports);
>>> +    destroy_tracked_lbs(&trk_changes->trk_lbs);
>>>      nd->change_tracked = false;
>>> -    nd->lb_changed = false;
>>> +}
>>> +
>>> +static void
>>> +init_northd_tracked_data(struct northd_data *nd)
>>> +{
>>> +    struct northd_tracked_data *trk_changes = &nd->trk_northd_changes;
>>> +    hmapx_init(&trk_changes->trk_ovn_ports.created);
>>> +    hmapx_init(&trk_changes->trk_ovn_ports.updated);
>>> +    hmapx_init(&trk_changes->trk_ovn_ports.deleted);
>>> +    hmapx_init(&trk_changes->trk_lbs.crupdated);
>>> +    hmapx_init(&trk_changes->trk_lbs.deleted);
>>> +}
>>> +
>>> +static void
>>> +destroy_northd_tracked_data(struct northd_data *nd)
>>> +{
>>> +    struct northd_tracked_data *trk_changes = &nd->trk_northd_changes;
>>> +    hmapx_destroy(&trk_changes->trk_ovn_ports.created);
>>> +    hmapx_destroy(&trk_changes->trk_ovn_ports.updated);
>>> +    hmapx_destroy(&trk_changes->trk_ovn_ports.deleted);
>>> +    hmapx_destroy(&trk_changes->trk_lbs.crupdated);
>>> +    hmapx_destroy(&trk_changes->trk_lbs.deleted);
>>> +}
>>> +
>>> +
>>> +bool
>>> +northd_has_tracked_data(struct northd_tracked_data *trk_nd_changes)
>>> +{
>>> +    return (!hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.created)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.updated)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.deleted)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_lbs.crupdated)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_lbs.deleted));
>>> +}
>>> +
>>> +bool
>>> +northd_has_only_ports_in_tracked_data(
>>> +    struct northd_tracked_data *trk_nd_changes)
>>> +{
>>> +    return (hmapx_is_empty(&trk_nd_changes->trk_lbs.crupdated)
>>> +            && hmapx_is_empty(&trk_nd_changes->trk_lbs.deleted)
>>> +            && (!hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.created)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.updated)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.deleted)));
>>> +}
>>> +

As far as I can tell the northd_has_only_ports_in_tracked_data() and
northd_has_tracked_data() are never used in this whole series.

What if we have a single function that returns a strong typed value
(enum) that identifies the change type instead?  Something like (not
tested, just compiled):

enum northd_tracked_data_type {
    NORTHD_TRACKED_NONE,
    NORTHD_TRACKED_PORTS = (1 << 0),
    NORTHD_TRACKED_LBS   = (1 << 1),
};

enum northd_tracked_data_type
northd_tracked_data_classify(const struct northd_tracked_data *trk_nd_changes)
{
    enum northd_tracked_data_type td_type = NORTHD_TRACKED_NONE;

    if (hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.created)
        && hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.updated)
        && hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.deleted)
        && hmapx_is_empty(&trk_nd_changes->trk_lbs.crupdated)
        && hmapx_is_empty(&trk_nd_changes->trk_lbs.deleted)) {
        goto done;
    }

    if (!hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.created)
        || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.updated)
        || !hmapx_is_empty(&trk_nd_changes->trk_ovn_ports.deleted)) {
        td_type |= NORTHD_TRACKED_PORTS;
    }

    if (!hmapx_is_empty(&trk_nd_changes->trk_lbs.crupdated)
        || !hmapx_is_empty(&trk_nd_changes->trk_lbs.deleted)) {
        td_type |= NORTHD_TRACKED_LBS;
    }

done:
    return td_type;
}

We can also get rid of northd_data->change_tracked, it's included
the northd_tracked_data structure implicitly.

>>> +bool
>>> +northd_has_lbs_in_tracked_data(struct northd_tracked_data
>> *trk_nd_changes)
>>> +{
>>> +    return (!hmapx_is_empty(&trk_nd_changes->trk_lbs.crupdated)
>>> +            || !hmapx_is_empty(&trk_nd_changes->trk_lbs.deleted));
>>>  }
>>>
>>>  /* Check if a changed LSP can be handled incrementally within the I-P
>> engine
>>> @@ -5344,12 +5404,12 @@ check_lsp_changes_other_than_up(const struct
>> nbrec_logical_switch_port *nbsp)
>>>   */
>>>  static bool
>>>  ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
>>> -                                const struct nbrec_logical_switch
>> *changed_ls,
>>> -                                const struct northd_input *ni,
>>> -                                struct northd_data *nd,
>>> -                                struct ovn_datapath *od,
>>> -                                struct ls_change *ls_change,
>>> -                                bool *updated)
>>> +                      const struct nbrec_logical_switch *changed_ls,
>>> +                      const struct northd_input *ni,
>>> +                      struct northd_data *nd,
>>> +                      struct ovn_datapath *od,
>>> +                      struct tracked_ovn_ports *trk_ports,
>>> +                      bool *updated)
>>>  {
>>>      bool ls_ports_changed = false;
>>>      if (!nbrec_logical_switch_is_updated(changed_ls,
>>> @@ -5370,7 +5430,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>          return true;
>>>      }
>>>
>>> -    ls_change->had_only_router_ports = (od->n_router_ports
>>> +    bool ls_had_only_router_ports = (od->n_router_ports
>>>              && (od->n_router_ports == hmap_count(&od->ports)));
>>>
>>>      struct ovn_port *op;
>>> @@ -5396,8 +5456,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>              if (!op) {
>>>                  goto fail;
>>>              }
>>> -            ovs_list_push_back(&ls_change->added_ports,
>>> -                                &op->list);
>>> +            add_op_to_northd_tracked_ports(&trk_ports->created, op);
>>>          } else if (ls_port_has_changed(op->nbsp, new_nbsp)) {
>>>              /* Existing port updated */
>>>              bool temp = false;
>>> @@ -5433,7 +5492,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>              if (!op) {
>>>                  goto fail;
>>>              }
>>> -            ovs_list_push_back(&ls_change->updated_ports, &op->list);
>>> +            add_op_to_northd_tracked_ports(&trk_ports->updated, op);
>>>          }
>>>          op->visited = true;
>>>      }
>>> @@ -5442,15 +5501,14 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>      HMAP_FOR_EACH_SAFE (op, dp_node, &od->ports) {
>>>          if (!op->visited) {
>>>              if (!op->lsp_can_be_inc_processed) {
>>> -                goto fail_clean_deleted;
>>> +                goto fail;
>>>              }
>>>              if (sset_contains(&nd->svc_monitor_lsps, op->key)) {
>>>                  /* This port was used for svc monitor, which may be
>>>                   * impacted by this deletion. Fallback to recompute. */
>>> -                goto fail_clean_deleted;
>>> +                goto fail;
>>>              }
>>> -            ovs_list_push_back(&ls_change->deleted_ports,
>>> -                                &op->list);
>>> +            add_op_to_northd_tracked_ports(&trk_ports->deleted, op);
>>>              hmap_remove(&nd->ls_ports, &op->key_node);
>>>              hmap_remove(&od->ports, &op->dp_node);
>>>              sbrec_port_binding_delete(op->sb);
>>> @@ -5459,20 +5517,29 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>          }
>>>      }
>>>
>>> -    if (!ovs_list_is_empty(&ls_change->added_ports) ||
>>> -        !ovs_list_is_empty(&ls_change->updated_ports) ||
>>> -        !ovs_list_is_empty(&ls_change->deleted_ports)) {
>>> +    bool ls_has_only_router_ports = (od->n_router_ports
>>> +            && (od->n_router_ports == hmap_count(&od->ports)));
>>> +
>>> +    /* If there were only router ports before the change or if there are
>> only
>>> +     * router ports after the change, then add the router ports of the
>>> +     * logical switch to the tracked 'updated' ovn ports. */
>>
>> This comment doesn't explain why we are doing this, so it may still be hard
>> to understand. The real reason as what I understand, is what explained in
>> the comment deleted by this patch:
>>          /* There are lflows related to router ports that depends on whether
>>           * there are switch ports on the logical switch (see
>>           * build_lswitch_rport_arp_req_flow() for more details). Since this
>>           * dependency changed, we need to regenerate lflows for each router
>>           * port on this logical switch. */
>> It may be better to incorporate that here.
> 
> Ack.
> 
> 
>>
>>> +    if (ls_had_only_router_ports != ls_has_only_router_ports) {
>>> +        for (size_t i = 0; i < od->n_router_ports; i++) {
>>> +            op = od->router_ports[i];
>>> +            add_op_to_northd_tracked_ports(&trk_ports->updated, op);
>>> +        }
>>> +    }
>>> +
>>> +    if (!hmapx_is_empty(&trk_ports->created) ||
>>> +        !hmapx_is_empty(&trk_ports->updated) ||
>>> +        !hmapx_is_empty(&trk_ports->deleted)) {
>>>          *updated = true;
>>>      }
>>>
>>>      return true;
>>>
>>> -fail_clean_deleted:
>>> -    LIST_FOR_EACH_POP (op, list, &ls_change->deleted_ports) {
>>> -        ovn_port_destroy_orphan(op);
>>> -    }
>>> -
>>>  fail:
>>> +    destroy_tracked_ovn_ports(trk_ports);
>>>      return false;
>>>  }
>>>
>>> @@ -5490,7 +5557,7 @@ northd_handle_ls_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>                           struct northd_data *nd)
>>>  {
>>>      const struct nbrec_logical_switch *changed_ls;
>>> -    struct ls_change *ls_change = NULL;
>>> +    struct northd_tracked_data *trk_nd_changes = &nd->trk_northd_changes;
>>>
>>>      NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH_TRACKED (changed_ls,
>>>
>> ni->nbrec_logical_switch_table) {
>>> @@ -5514,33 +5581,18 @@ northd_handle_ls_changes(struct ovsdb_idl_txn
>> *ovnsb_idl_txn,
>>>              goto fail;
>>>          }
>>>
>>> -        ls_change = xzalloc(sizeof *ls_change);
>>> -        ls_change->od = od;
>>> -        ovs_list_init(&ls_change->added_ports);
>>> -        ovs_list_init(&ls_change->deleted_ports);
>>> -        ovs_list_init(&ls_change->updated_ports);
>>> -
>>>          bool updated = false;
>>>          if (!ls_handle_lsp_changes(ovnsb_idl_txn, changed_ls,
>>> -                                   ni, nd, od, ls_change,
>>> +                                   ni, nd, od,
>> &trk_nd_changes->trk_ovn_ports,
>>>                                     &updated)) {
>>> -            destroy_tracked_ls_change(ls_change);
>>> -            free(ls_change);
>>>              goto fail;
>>>          }
>>>
>>>          if (updated) {
>>> -            ovs_list_push_back(&nd->tracked_ls_changes.updated,
>>> -                               &ls_change->list_node);
>>> -        } else {
>>> -            free(ls_change);
>>> +            nd->change_tracked = true;
>>>          }
>>>      }
>>>
>>> -    if (!ovs_list_is_empty(&nd->tracked_ls_changes.updated)) {
>>> -        nd->change_tracked = true;
>>> -    }
>>> -
>>>      return true;
>>>
>>>  fail:
>>> @@ -5715,7 +5767,8 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>                                struct ovn_datapaths *ls_datapaths,
>>>                                struct ovn_datapaths *lr_datapaths,
>>>                                struct hmap *lb_datapaths_map,
>>> -                              struct hmap *lbgrp_datapaths_map)
>>> +                              struct hmap *lbgrp_datapaths_map,
>>> +                              struct northd_tracked_data *nd_changes)
>>>  {
>>>      if (trk_lb_data->has_health_checks) {
>>>          /* Fall back to recompute since a tracked load balancer
>>> @@ -5778,7 +5831,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>          }
>>>
>>>          hmap_remove(lb_datapaths_map, &lb_dps->hmap_node);
>>> -        ovn_lb_datapaths_destroy(lb_dps);
>>> +
>>> +        /* Add the deleted lb to the northd tracked data. */
>>> +        hmapx_add(&nd_changes->trk_lbs.deleted, lb_dps);
>>>      }
>>>
>>>      /* Create the 'lb_dps' if not already created for each
>>> @@ -5795,6 +5850,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>              hmap_insert(lb_datapaths_map, &lb_dps->hmap_node,
>>>                          uuid_hash(lb_uuid));
>>>          }
>>> +
>>> +        /* Add the updated lb to the northd tracked data. */
>>> +        hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>      }
>>>
>>>      struct ovn_lb_group_datapaths *lbgrp_dps;
>>> @@ -5825,6 +5883,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>              lb_dps = ovn_lb_datapaths_find(lb_datapaths_map,
>> &uuidnode->uuid);
>>>              ovs_assert(lb_dps);
>>>              ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
>>> +
>>> +            /* Add the lb to the northd tracked data. */
>>> +            hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>          }
>>>
>>>          UUIDSET_FOR_EACH (uuidnode, &codlb->assoc_lbgrps) {
>>> @@ -5840,6 +5901,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>                  lb_dps = ovn_lb_datapaths_find(lb_datapaths_map,
>> lb_uuid);
>>>                  ovs_assert(lb_dps);
>>>                  ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
>>> +
>>> +                /* Add the lb to the northd tracked data. */
>>> +                hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>              }
>>>          }
>>>
>>> @@ -5860,6 +5924,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>              /* Add the lb_ips of lb_dps to the od. */
>>>              build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
>>>              build_lrouter_lb_reachable_ips(od, lb_dps->lb);
>>> +
>>> +            /* Add the lb to the northd tracked data. */
>>> +            hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>          }
>>>
>>>          UUIDSET_FOR_EACH (uuidnode, &codlb->assoc_lbgrps) {
>>> @@ -5879,6 +5946,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>                  /* Add the lb_ips of lb_dps to the od. */
>>>                  build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
>>>                  build_lrouter_lb_reachable_ips(od, lb_dps->lb);
>>> +
>>> +                /* Add the lb to the northd tracked data. */
>>> +                hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>              }
>>>          }
>>>
>>> @@ -5957,6 +6027,9 @@ northd_handle_lb_data_changes(struct
>> tracked_lb_data *trk_lb_data,
>>>                  /* Re-evaluate 'od->has_lb_vip' */
>>>                  init_lb_for_datapath(od);
>>>              }
>>> +
>>> +            /* Add the lb to the northd tracked data. */
>>> +            hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
>>>          }
>>>      }
>>>
>>> @@ -16996,149 +17069,125 @@ delete_lflow_for_lsp(struct ovn_port *op,
>> bool is_update,
>>>      return true;
>>>  }
>>>
>>> -bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn,
>>> -                                    struct tracked_ls_changes
>> *ls_changes,
>>> -                                    struct lflow_input *lflow_input,
>>> -                                    struct hmap *lflows)
>>> +bool
>>> +lflow_handle_northd_port_changes(struct ovsdb_idl_txn *ovnsb_txn,
>>> +                                 struct tracked_ovn_ports *trk_ovn_ports,
>>> +                                 struct lflow_input *lflow_input,
>>> +                                 struct hmap *lflows)
>>>  {
>>> -    struct ls_change *ls_change;
>>> +    struct hmapx_node *hmapx_node;
>>> +    struct ovn_port *op;
>>>
>>> -    LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
>>> -        const struct sbrec_multicast_group *sbmc_flood =
>>> -            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> -                               MC_FLOOD, ls_change->od->sb);
>>> -        const struct sbrec_multicast_group *sbmc_flood_l2 =
>>> -            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> -                               MC_FLOOD_L2, ls_change->od->sb);
>>> -        const struct sbrec_multicast_group *sbmc_unknown =
>>> -            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> -                               MC_UNKNOWN, ls_change->od->sb);
>>> +    HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->deleted) {
>>> +        op = hmapx_node->data;
>>> +        /* We don't support lflow handling for deleted logical router
>>> +         * ports yet. */
>>> +        ovs_assert(op->nbsp);
>>>
>>> -        struct ovn_port *op;
>>> -        LIST_FOR_EACH (op, list, &ls_change->deleted_ports) {
>>> -            if (!delete_lflow_for_lsp(op, false,
>>> -
>>  lflow_input->sbrec_logical_flow_table,
>>> -                                      lflows)) {
>>> +        if (!delete_lflow_for_lsp(op, false,
>>> +                                  lflow_input->sbrec_logical_flow_table,
>>> +                                  lflows)) {
>>>                  return false;
>>>              }
>>>
>>> -            /* No need to update SB multicast groups, thanks to weak
>>> -             * references. */
>>> -        }
>>> +        /* No need to update SB multicast groups, thanks to weak
>>> +         * references. */
>>> +    }
>>>
>>> -        LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
>>> -            /* Delete old lflows. */
>>> -            if (!delete_lflow_for_lsp(op, true,
>>> -
>>  lflow_input->sbrec_logical_flow_table,
>>> -                                      lflows)) {
>>> -                return false;
>>> -            }
>>> +    HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->updated) {
>>> +        op = hmapx_node->data;
>>> +        /* We don't support lflow handling for updated logical router
>>> +         * ports yet. */
>>> +        ovs_assert(op->nbsp);
>>>
>>> -            /* Generate new lflows. */
>>> -            struct ds match = DS_EMPTY_INITIALIZER;
>>> -            struct ds actions = DS_EMPTY_INITIALIZER;
>>> -            build_lswitch_and_lrouter_iterate_by_lsp(op,
>> lflow_input->ls_ports,
>>> -
>> lflow_input->lr_ports,
>>> -
>> lflow_input->meter_groups,
>>> -                                                     &match, &actions,
>>> -                                                     lflows);
>>> -            ds_destroy(&match);
>>> -            ds_destroy(&actions);
>>> -
>>> -            /* SB port_binding is not deleted, so don't update SB
>> multicast
>>> -             * groups. */
>>> -
>>> -            /* Sync the new flows to SB. */
>>> -            struct lflow_ref_node *lfrn;
>>> -            LIST_FOR_EACH (lfrn, lflow_list_node, &op->lflows) {
>>> -                sync_lsp_lflows_to_sb(ovnsb_txn, lflow_input, lflows,
>>> -                                      lfrn->lflow);
>>> -            }
>>> +        /* Delete old lflows. */
>>> +        if (!delete_lflow_for_lsp(op, true,
>>> +                                  lflow_input->sbrec_logical_flow_table,
>>> +                                  lflows)) {
>>> +            return false;
>>>          }
>>>
>>> -        LIST_FOR_EACH (op, list, &ls_change->added_ports) {
>>> -            struct ds match = DS_EMPTY_INITIALIZER;
>>> -            struct ds actions = DS_EMPTY_INITIALIZER;
>>> -            build_lswitch_and_lrouter_iterate_by_lsp(op,
>> lflow_input->ls_ports,
>>> -
>> lflow_input->lr_ports,
>>> -
>> lflow_input->meter_groups,
>>> -                                                     &match, &actions,
>>> -                                                     lflows);
>>> -            ds_destroy(&match);
>>> -            ds_destroy(&actions);
>>> -
>>> -            /* Update SB multicast groups for the new port. */
>>> -            if (!sbmc_flood) {
>>> -                sbmc_flood = create_sb_multicast_group(ovnsb_txn,
>>> -                    ls_change->od->sb, MC_FLOOD,
>> OVN_MCAST_FLOOD_TUNNEL_KEY);
>>> -            }
>>> -            sbrec_multicast_group_update_ports_addvalue(sbmc_flood,
>> op->sb);
>>> +        /* Generate new lflows. */
>>> +        struct ds match = DS_EMPTY_INITIALIZER;
>>> +        struct ds actions = DS_EMPTY_INITIALIZER;
>>> +        build_lswitch_and_lrouter_iterate_by_lsp(op,
>> lflow_input->ls_ports,
>>> +                                                 lflow_input->lr_ports,
>>> +
>> lflow_input->meter_groups,
>>> +                                                 &match, &actions,
>>> +                                                 lflows);
>>> +        ds_destroy(&match);
>>> +        ds_destroy(&actions);
>>>
>>> -            if (!sbmc_flood_l2) {
>>> -                sbmc_flood_l2 = create_sb_multicast_group(ovnsb_txn,
>>> -                    ls_change->od->sb, MC_FLOOD_L2,
>>> -                    OVN_MCAST_FLOOD_L2_TUNNEL_KEY);
>>> -            }
>>> -            sbrec_multicast_group_update_ports_addvalue(sbmc_flood_l2,
>> op->sb);
>>> -
>>> -            if (op->has_unknown) {
>>> -                if (!sbmc_unknown) {
>>> -                    sbmc_unknown = create_sb_multicast_group(ovnsb_txn,
>>> -                        ls_change->od->sb, MC_UNKNOWN,
>>> -                        OVN_MCAST_UNKNOWN_TUNNEL_KEY);
>>> -                }
>>> -                sbrec_multicast_group_update_ports_addvalue(sbmc_unknown,
>>> -                                                            op->sb);
>>> -            }
>>> +        /* SB port_binding is not deleted, so don't update SB multicast
>>> +         * groups. */
>>>
>>> -            /* Sync the newly added flows to SB. */
>>> -            struct lflow_ref_node *lfrn;
>>> -            LIST_FOR_EACH (lfrn, lflow_list_node, &op->lflows) {
>>> -                sync_lsp_lflows_to_sb(ovnsb_txn, lflow_input, lflows,
>>> -                                      lfrn->lflow);
>>> -            }
>>> +        /* Sync the new flows to SB. */
>>> +        struct lflow_ref_node *lfrn;
>>> +        LIST_FOR_EACH (lfrn, lflow_list_node, &op->lflows) {
>>> +            sync_lsp_lflows_to_sb(ovnsb_txn, lflow_input, lflows,
>>> +                                  lfrn->lflow);
>>>          }
>>> +    }
>>>
>>> -        bool ls_has_only_router_ports = (ls_change->od->n_router_ports &&
>>> -                                         (ls_change->od->n_router_ports
>> ==
>>> -
>>  hmap_count(&ls_change->od->ports)));
>>> -
>>> -        if (ls_change->had_only_router_ports !=
>> ls_has_only_router_ports) {
>>> -            /* There are lflows related to router ports that depends on
>> whether
>>> -             * there are switch ports on the logical switch (see
>>> -             * build_lswitch_rport_arp_req_flow() for more details).
>> Since this
>>> -             * dependency changed, we need to regenerate lflows for each
>> router
>>> -             * port on this logical switch. */
>>> -            for (size_t i = 0; i < ls_change->od->n_router_ports; i++) {
>>> -                op = ls_change->od->router_ports[i];
>>> -
>>> -                /* Delete old lflows. */
>>> -                if (!delete_lflow_for_lsp(op, "affected router",
>>> -
>>  lflow_input->sbrec_logical_flow_table,
>>> -                                      lflows)) {
>>> -                    return false;
>>> -                }
>>> +    HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->created) {
>>> +        op = hmapx_node->data;
>>> +        /* We don't support lflow handling for created logical router
>>> +         * ports yet. */
>>> +        ovs_assert(op->nbsp);
>>>
>>> -                /* Generate new lflows. */
>>> -                struct ds match = DS_EMPTY_INITIALIZER;
>>> -                struct ds actions = DS_EMPTY_INITIALIZER;
>>> -                build_lswitch_and_lrouter_iterate_by_lsp(op,
>>> -                    lflow_input->ls_ports, lflow_input->lr_ports,
>>> -                    lflow_input->meter_groups, &match, &actions, lflows);
>>> -                ds_destroy(&match);
>>> -                ds_destroy(&actions);
>>> -
>>> -                /* Sync the new flows to SB. */
>>> -                struct lflow_ref_node *lfrn;
>>> -                LIST_FOR_EACH (lfrn, lflow_list_node, &op->lflows) {
>>> -                    sync_lsp_lflows_to_sb(ovnsb_txn, lflow_input, lflows,
>>> -                                          lfrn->lflow);
>>> -                }
>>> +        const struct sbrec_multicast_group *sbmc_flood =
>>> +            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> +                               MC_FLOOD, op->od->sb);
>>> +        const struct sbrec_multicast_group *sbmc_flood_l2 =
>>> +            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> +                               MC_FLOOD_L2, op->od->sb);
>>> +        const struct sbrec_multicast_group *sbmc_unknown =
>>> +            mcast_group_lookup(lflow_input->sbrec_mcast_group_by_name_dp,
>>> +                               MC_UNKNOWN, op->od->sb);
>>> +
>>> +        struct ds match = DS_EMPTY_INITIALIZER;
>>> +        struct ds actions = DS_EMPTY_INITIALIZER;
>>> +        build_lswitch_and_lrouter_iterate_by_lsp(op,
>> lflow_input->ls_ports,
>>> +
>>  lflow_input->lr_ports,
>>> +
>>  lflow_input->meter_groups,
>>> +                                                    &match, &actions,
>>> +                                                    lflows);
>>> +        ds_destroy(&match);
>>> +        ds_destroy(&actions);
>>> +
>>> +        /* Update SB multicast groups for the new port. */
>>> +        if (!sbmc_flood) {
>>> +            sbmc_flood = create_sb_multicast_group(ovnsb_txn,
>>> +                op->od->sb, MC_FLOOD, OVN_MCAST_FLOOD_TUNNEL_KEY);
>>> +        }
>>> +        sbrec_multicast_group_update_ports_addvalue(sbmc_flood, op->sb);
>>> +
>>> +        if (!sbmc_flood_l2) {
>>> +            sbmc_flood_l2 = create_sb_multicast_group(ovnsb_txn,
>>> +                op->od->sb, MC_FLOOD_L2,
>>> +                OVN_MCAST_FLOOD_L2_TUNNEL_KEY);
>>> +        }
>>> +        sbrec_multicast_group_update_ports_addvalue(sbmc_flood_l2,
>> op->sb);
>>> +
>>> +        if (op->has_unknown) {
>>> +            if (!sbmc_unknown) {
>>> +                sbmc_unknown = create_sb_multicast_group(ovnsb_txn,
>>> +                    op->od->sb, MC_UNKNOWN,
>>> +                    OVN_MCAST_UNKNOWN_TUNNEL_KEY);
>>>              }
>>> +            sbrec_multicast_group_update_ports_addvalue(sbmc_unknown,
>>> +                                                        op->sb);
>>> +        }
>>> +
>>> +        /* Sync the newly added flows to SB. */
>>> +        struct lflow_ref_node *lfrn;
>>> +        LIST_FOR_EACH (lfrn, lflow_list_node, &op->lflows) {
>>> +            sync_lsp_lflows_to_sb(ovnsb_txn, lflow_input, lflows,
>>> +                                    lfrn->lflow);
>>>          }
>>>      }
>>> -    return true;
>>>
>>> +    return true;
>>>  }
>>>
>>>  static bool
>>> @@ -17771,7 +17820,7 @@ northd_init(struct northd_data *data)
>>>      sset_init(&data->svc_monitor_lsps);
>>>      hmap_init(&data->svc_monitor_map);
>>>      data->change_tracked = false;
>>> -    ovs_list_init(&data->tracked_ls_changes.updated);
>>> +    init_northd_tracked_data(data);
>>>  }
>>>
>>>  void
>>> @@ -17811,6 +17860,7 @@ northd_destroy(struct northd_data *data)
>>>      destroy_debug_config();
>>>
>>>      sset_destroy(&data->svc_monitor_lsps);
>>> +    destroy_northd_tracked_data(data);
>>>  }
>>>
>>>  void
>>> diff --git a/northd/northd.h b/northd/northd.h
>>> index 5be7b5384d..2e4f125902 100644
>>> --- a/northd/northd.h
>>> +++ b/northd/northd.h
>>> @@ -83,22 +83,36 @@ struct ovn_datapaths {
>>>      struct ovn_datapath **array;
>>>  };
>>>
>>> -/* Track what's changed for a single LS.
>>> - * Now only track port changes. */
>>> -struct ls_change {
>>> -    struct ovs_list list_node;
>>> -    struct ovn_datapath *od;
>>> -    struct ovs_list added_ports;
>>> -    struct ovs_list deleted_ports;
>>> -    struct ovs_list updated_ports;
>>> -    bool had_only_router_ports;
>>> +struct tracked_ovn_ports {
>>> +    /* tracked created ports.
>>> +     * hmapx node data is 'struct ovn_port *' */
>>> +    struct hmapx created;
>>> +
>>> +    /* tracked updated ports.
>>> +     * hmapx node data is 'struct ovn_port *' */
>>> +    struct hmapx updated;
>>> +
>>> +    /* tracked deleted ports.
>>> +     * hmapx node data is 'struct ovn_port *' */
>>> +    struct hmapx deleted;
>>>  };
>>
>> Is there a reason why changing the structures from list to hmapx? It seems
>> to me the tracked ports will be traversed one by one and doesn't require
>> searching.
> 
> Yes.  There is a reason.  The lflow engine node which uses this
> tracked data will
> not search for it.  It just needs to iterate the changed ovn_ports. So
> it doesn't matter
> if it is a list or hmapx.
> 
> But it becomes easier to add changed ovn_ports to hmapx and there is no need 
> to
> have a list node in the 'struct ovn_port'.
> 
>>
>>>
>>> -/* Track what's changed for logical switches.
>>> - * Now only track updated ones (added or deleted may be supported in the
>>> - * future). */
>>> -struct tracked_ls_changes {
>>> -    struct ovs_list updated; /* Contains struct ls_change */
>>> +struct tracked_lbs {
>>> +    /* Tracked created or updated load balancers.
>>> +     * hmapx node data is 'struct ovn_lb_datapaths' */
>>> +    struct hmapx crupdated;
>>> +
>>> +    /* Tracked deleted lbs.
>>> +     * hmapx node data is 'struct ovn_lb_datapaths' */
>>> +    struct hmapx deleted;
>>> +};
>>> +
>>> +/* Track what's changed in the northd engine node.
>>> + * Now only tracks ovn_ports (of vif type) - created, updated
>>> + * and deleted. */
>>> +struct northd_tracked_data {
>>> +    struct tracked_ovn_ports trk_ovn_ports;
>>
>> It may be better to name it trk_lsps or something similar, so that it is
>> clear that the field is tracking LSPs, not LRPs.
> 
> Ack.
> 
> 
>>
>>> +    struct tracked_lbs trk_lbs;
>>>  };
>>>
>>>  struct northd_data {
>>> @@ -114,10 +128,9 @@ struct northd_data {
>>>      struct chassis_features features;
>>>      struct sset svc_monitor_lsps;
>>>      struct hmap svc_monitor_map;
>>> +    /* Indicates if northd engine node has changes tracked or not. */
>>>      bool change_tracked;
>>> -    struct tracked_ls_changes tracked_ls_changes;
>>> -    bool lb_changed; /* Indicates if load balancers changed or
>> association of
>>> -                      * load balancer to logical switch/router changed.
>> */
>>> +    struct northd_tracked_data trk_northd_changes;
>>>  };
>>>
>>>  struct lflow_data {
>>> @@ -338,9 +351,10 @@ void northd_indices_create(struct northd_data *data,
>>>  void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
>>>                    struct lflow_input *input_data,
>>>                    struct hmap *lflows);
>>> -bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn,
>>> -                                    struct tracked_ls_changes *,
>>> -                                    struct lflow_input *, struct hmap
>> *lflows);
>>> +bool lflow_handle_northd_port_changes(struct ovsdb_idl_txn *ovnsb_txn,
>>> +                                      struct tracked_ovn_ports *,
>>> +                                      struct lflow_input *,
>>> +                                      struct hmap *lflows);
>>>  bool northd_handle_sb_port_binding_changes(
>>>      const struct sbrec_port_binding_table *, struct hmap *ls_ports);
>>>
>>> @@ -349,7 +363,8 @@ bool northd_handle_lb_data_changes(struct
>> tracked_lb_data *,
>>>                                     struct ovn_datapaths *ls_datapaths,
>>>                                     struct ovn_datapaths *lr_datapaths,
>>>                                     struct hmap *lb_datapaths_map,
>>> -                                   struct hmap *lbgrp_datapaths_map);
>>> +                                   struct hmap *lbgrp_datapaths_map,
>>> +                                   struct northd_tracked_data *);
>>>
>>>  void build_bfd_table(struct ovsdb_idl_txn *ovnsb_txn,
>>>                       const struct nbrec_bfd_table *,
>>> @@ -372,6 +387,10 @@ void sync_lbs(struct ovsdb_idl_txn *, const struct
>> sbrec_load_balancer_table *,
>>>  bool check_sb_lb_duplicates(const struct sbrec_load_balancer_table *);
>>>
>>>  void sync_pbs(struct ovsdb_idl_txn *, struct hmap *ls_ports);
>>> -bool sync_pbs_for_northd_ls_changes(struct tracked_ls_changes *);
>>> +bool sync_pbs_for_northd_changed_ovn_ports( struct tracked_ovn_ports *);
>>> +
>>> +bool northd_has_tracked_data(struct northd_tracked_data *);
>>> +bool northd_has_only_ports_in_tracked_data(struct northd_tracked_data *);
>>> +bool northd_has_lbs_in_tracked_data(struct northd_tracked_data *);
>>>
>>>  #endif /* NORTHD_H */
>>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>>> index 196fe01fbd..28c293473c 100644
>>> --- a/tests/ovn-northd.at
>>> +++ b/tests/ovn-northd.at
>>> @@ -10620,10 +10620,9 @@ check as northd ovn-appctl -t NORTHD_TYPE
>> inc-engine/clear-stats
>>>  lbg1_uuid=$(ovn-nbctl --wait=sb create load_balancer_group name=lbg1)
>>>  check_engine_stats lb_data norecompute compute
>>>  check_engine_stats northd norecompute compute
>>> -check_engine_stats lflow recompute nocompute
>>> -check_engine_stats sync_to_sb_lb nocompute nocompute
>>
>> Why remove this check for sync_to_sb_lb?
>>
> 
> I think I removed it by mistake.
> 
> With this patch 'sync_to_sb_lb' will not result in recompute when you
> create an empty load balancer group  (i.e lb group not having any load
> balancer in it).
> The same is true for 'lflow' engine node too.
> 
> The reason is - northd_lb_data_handler() before this patch was setting
> northd_data->lb_changed = true for any lb_data change.
> northd handler for lflow engine and sync_to_sb_lb fall back to
> recompute if northd_data->lb_changed = true.
> 
> But with this patch,   northd_data->lb_changed is removed and we use
> the tracking data of the northd.
> 
> ------
> /* Fall back to recompute if load balancers have changed. */
> if (northd_has_lbs_in_tracked_data(&northd_data->trk_northd_changes)) {
> return false;
> }
> ----
> 
> 
> 
>>> -
>>> +check_engine_stats lflow norecompute nocompute
>>
>> Could you explain what change in this patch avoided the recompute of lflow?
>> It is not obvious to me and it is not mentioned in the commit message.
> 
> Please see above.  I'll update the commit message.
> 
> Thanks for the reviews.
> 
> Numan
> 
> 
>>
>>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>> +
>>>  check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>>>
>>>  lb1_uuid=$(fetch_column nb:Load_Balancer _uuid)
>>> @@ -10650,7 +10649,6 @@ check_engine_stats lb_data norecompute compute
>>>  check_engine_stats northd norecompute compute
>>>  check_engine_stats lflow recompute nocompute
>>>  check_engine_stats sync_to_sb_lb recompute nocompute
>>> -
>>>  CHECK_NO_CHANGE_AFTER_RECOMPUTE
>>>
>>>  check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>>> @@ -10798,8 +10796,8 @@ check as northd ovn-appctl -t NORTHD_TYPE
>> inc-engine/clear-stats
>>>  lbg1_uuid=$(ovn-nbctl --wait=sb create load_balancer_group name=lbg1)
>>>  check_engine_stats lb_data norecompute compute
>>>  check_engine_stats northd norecompute compute
>>> -check_engine_stats lflow recompute nocompute
>>> -check_engine_stats sync_to_sb_lb recompute nocompute
>>> +check_engine_stats lflow norecompute nocompute
>>> +check_engine_stats sync_to_sb_lb norecompute nocompute
>>>
>>>  check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
>>>  check ovn-nbctl --wait=sb set load_balancer_group .
>> load_balancer="$lb2_uuid,$lb3_uuid,$lb4_uuid"
>>> --
>>> 2.41.0
>>>
>>> _______________________________________________
>>> 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
> 
> _______________________________________________
> 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