Hi Jacob, Dumitriu,

Thanks for your review and merged.



Em qui., 17 de set. de 2026 às 10:03, Jacob Tanenbaum <[email protected]>
escreveu:

>
>
> On Thu, Sep 17, 2026 at 3:20 AM Dumitru Ceara <[email protected]> wrote:
>
>> Hi Lucas, Jacob,
>>
>> On 9/16/26 10:17 PM, Jacob Tanenbaum via dev wrote:
>> > Thanks for the patch Lucas! Sorry it took so long to review this. This
>> > looks good to me.
>> >
>>
>> Lucas, thanks for the fix and Jacob, thanks for the review!
>>
>> > I am wondering if replacing the refcount with an actual counter would
>> help
>> > us in the future?
>> >
>>
>> I'm sorry, I must be missing something, I don't get it.  A reference
>> counter is a counter, what's an "actual counter"?
>>
>
> What I mean is the first reference to the flow does not create the
> refcount so it only starts counting when refcount = 2 but once the refcount
> is created it isn't cleaned up until it reaches zero. This leads to the
> observation below.
>



>
>
>>
>> > Currently, if no refcnt entry is created, it means there is at most one
>> > live reference. If a refcount
>> > entry exists, it holds the total live references, which are removed
>> only at
>> > zero. Returning true from
>> > dp_refcount_release() when !dp_refcount does not allow us to distinguish
>> > from two different situations
>> >
>> >    1. it is the flows only reference (correct)
>> >    2. the entry should exist but is missing (bug)
>> >
>> > This is just a thought and should not block this patch.
>> >
>>
>> Do you mean this?
>>
>
> Yes, this patch didn't introduce this refcount and it maintains how it is
> being used correctly. I was just wondering if putting in the work to change
> the refcount would clear up this potential source of confusion in the
> future.
>
>
>

I agree, Jacob. About the asymmetry: the entry is allocated on the second
use,
so it is born holding 2, but it is only freed at 0. "One live reference"
therefore has
two representations, and the entry holding 1 is a dead state that keeps the
allocation around.

Always allocating isn't an option: that encoding comes from commit
0e0f38f1a293 ("northd: lflow-mgr: Allocate DP reference counters on a second
use."), which deferred it because most counters are 1.

We could get the clarity for free, though, by freeing the entry when it
drops
back to a single reference instead of to zero. What do you think?

The representation becomes canonical — an entry exists iff there are two or
more references, and it holds the exact count — and
ovs_assert(dp_refcnt->refcnt > 1) becomes a real invariant. It frees entries
earlier, so it can only help the numbers above.

That still doesn't tell your case 2 apart, which needs the true count. The
other half is cheap though: when dp_refcnt_release() finds no entry, the bit
in lflow->dpg_bitmap must be set, so asserting that catches releasing a
datapath the lflow doesn't hold.

What actually gets lost is not the count but the set of datapaths:
lrn->dpgrp_bitmap is cloned when the
lflow_ref_node is created and never updated, while the references are taken
from the bitmap the client passes on every link. That leaves an lflow
applied to a datapath that no longer generates it, and it makes ovn-northd
abort on ovs_assert(lrn->dpgrp_bitmap_len == dp_bitmap_len) when a logical
router created without ports grows ods_size(lr_datapaths).


Regards,
Lucas


>
>> diff --git a/northd/lflow-mgr.c b/northd/lflow-mgr.c
>> index ce9c4f8543..ac4ef72d0e 100644
>> --- a/northd/lflow-mgr.c
>> +++ b/northd/lflow-mgr.c
>> @@ -1462,10 +1462,12 @@ static bool
>>  dp_refcnt_release(struct hmap *dp_refcnts_map, size_t dp_index)
>>  {
>>      struct dp_refcnt *dp_refcnt = dp_refcnt_find(dp_refcnts_map,
>> dp_index);
>> +    ovs_assert(dp_refcnt);
>>      if (!dp_refcnt) {
>>          return true;
>>      }
>>
>> +    ovs_assert(dp_refcnt->refcnt > 0);
>>      if (!--dp_refcnt->refcnt) {
>>          hmap_remove(dp_refcnts_map, &dp_refcnt->key_node);
>>          free(dp_refcnt);
>>
>> > Acked-by: Jacob Tanenbaum <[email protected]>
>> >
>>
>> I'll be applying this patch to main and 26.09 soon.
>>
>> Thanks again!
>>
>> Regards,
>> Dumitru
>>
>> > On Thu, Aug 20, 2026 at 3:24 PM Lucas Vargas Dias
>> <[email protected]>
>> > wrote:
>> >
>> >> Commit 0e2bcf70ac4f moved the release of the dp group referenced by an
>> >> lflow from sync_lflow_to_sb() to do_ovn_lflow_add(), so that the group
>> is
>> >> already free when a new one is looked up and the SB row can be reused.
>> >> However, do_ovn_lflow_add() is only called when the lflow is generated
>> >> again.  An lflow that is merely unlinked from one of its lflow_refs,
>> and
>> >> that survives because other lflow_refs still reference it, never goes
>> >> through do_ovn_lflow_add(): only its dp group bitmap shrinks.  Such an
>> >> lflow is synced with a different dp group (or with a single datapath),
>> >> and the reference to the previous group is never dropped.
>> >>
>> >> The leaked group stays in the 'dp_groups' map with a non zero refcount
>> >> while no lflow uses it anymore, so its SB Logical_DP_Group row is
>> garbage
>> >> collected.  Any lflow that later needs that same set of datapaths finds
>> >> the leaked group, fails to look its row up and northd logs:
>> >>
>> >>   SB Logical flow [...]'s logical_dp_group column is not set (which is
>> >>   unexpected).  It should have been referencing the dp group [...]
>> >>
>> >> and falls back to a full recompute.
>> >>
>> >> Release the group in lflow_ref_unlink_lflows(), where the bitmap
>> actually
>> >> shrinks.  Like the release done by do_ovn_lflow_add(), this happens
>> before
>> >> any lflow of the round is synced, which is what allows
>> >> ovn_dp_group_create() to modify the SB row of a group that just became
>> >> free instead of inserting a new row and leaving the old one to be
>> deleted.
>> >> Releasing at sync time would fix the leak but not that churn: a group
>> is
>> >> usually referenced by several lflows, so it is still in 'dp_groups'
>> when
>> >> the first of them is synced.
>> >>
>> >> Fixes: 0e2bcf70ac4f ("northd: Change ovn_dp_groups to decrement
>> refcount
>> >> in do_ovn_lflow_add.")
>> >> Assisted-by: Claude Opus 5, Claude Code
>> >> Signed-off-by: Lucas Vargas Dias <[email protected]>
>> >> ---
>> >>  northd/en-lflow.c   |  6 ++-
>> >>  northd/lflow-mgr.c  | 39 ++++++++++++++++---
>> >>  northd/lflow-mgr.h  |  2 +-
>> >>  northd/northd.c     | 16 ++++----
>> >>  tests/ovn-northd.at | 94
>> +++++++++++++++++++++++++++++++++++++++++++++
>> >>  5 files changed, 140 insertions(+), 17 deletions(-)
>> >>
>> >> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
>> >> index 8cb987777..e8e6cdaa2 100644
>> >> --- a/northd/en-lflow.c
>> >> +++ b/northd/en-lflow.c
>> >> @@ -294,7 +294,8 @@ lflow_group_ecmp_route_change_handler(struct
>> >> engine_node *node,
>> >>      HMAPX_FOR_EACH (hmapx_node,
>> >>
>> >>  &group_ecmp_route_data->trk_data.deleted_datapath_routes) {
>> >>          route_node = hmapx_node->data;
>> >> -        lflow_ref_unlink_lflows(route_node->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(route_node->lflow_ref,
>> >> +                                lflow_data->lflow_table);
>> >>
>> >>          bool handled = lflow_ref_sync_lflows(
>> >>              route_node->lflow_ref, lflow_data->lflow_table,
>> >> @@ -312,7 +313,8 @@ lflow_group_ecmp_route_change_handler(struct
>> >> engine_node *node,
>> >>          &group_ecmp_route_data->trk_data.crupdated_datapath_routes;
>> >>      HMAPX_FOR_EACH (hmapx_node, crupdated_datapath_routes) {
>> >>          route_node = hmapx_node->data;
>> >> -        lflow_ref_unlink_lflows(route_node->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(route_node->lflow_ref,
>> >> +                                lflow_data->lflow_table);
>> >>          build_route_data_flows_for_lrouter(
>> >>              route_node->od, lflow_data->lflow_table,
>> >>              route_node, lflow_input.bfd_ports);
>> >> diff --git a/northd/lflow-mgr.c b/northd/lflow-mgr.c
>> >> index ce9c4f854..f51df9ce0 100644
>> >> --- a/northd/lflow-mgr.c
>> >> +++ b/northd/lflow-mgr.c
>> >> @@ -657,26 +657,53 @@ lflow_ref_destroy(struct lflow_ref *lflow_ref)
>> >>   * from the lrn->lflow's dpg bitmap
>> >>   */
>> >>  void
>> >> -lflow_ref_unlink_lflows(struct lflow_ref *lflow_ref)
>> >> +lflow_ref_unlink_lflows(struct lflow_ref *lflow_ref,
>> >> +                        struct lflow_table *lflow_table)
>> >>  {
>> >>      struct lflow_ref_node *lrn;
>> >>
>> >>      HMAP_FOR_EACH (lrn, ref_node, &lflow_ref->lflow_ref_nodes) {
>> >> +        struct ovn_lflow *lflow = lrn->lflow;
>> >> +        bool dpg_bitmap_changed = false;
>> >> +
>> >>          if (lrn->dpgrp_lflow) {
>> >>              size_t index;
>> >>              BITMAP_FOR_EACH_1 (index, lrn->dpgrp_bitmap_len,
>> >>                                 lrn->dpgrp_bitmap) {
>> >> -                if (dp_refcnt_release(&lrn->lflow->dp_refcnts_map,
>> >> index)) {
>> >> -                    dynamic_bitmap_set0(&lrn->lflow->dpg_bitmap,
>> index);
>> >> +                if (dp_refcnt_release(&lflow->dp_refcnts_map, index))
>> {
>> >> +                    dynamic_bitmap_set0(&lflow->dpg_bitmap, index);
>> >> +                    dpg_bitmap_changed = true;
>> >>                  }
>> >>              }
>> >>          } else {
>> >> -            if (dp_refcnt_release(&lrn->lflow->dp_refcnts_map,
>> >> +            if (dp_refcnt_release(&lflow->dp_refcnts_map,
>> >>                                    lrn->dp_index)) {
>> >> -                dynamic_bitmap_set0(&lrn->lflow->dpg_bitmap,
>> >> lrn->dp_index);
>> >> +                dynamic_bitmap_set0(&lflow->dpg_bitmap,
>> lrn->dp_index);
>> >> +                dpg_bitmap_changed = true;
>> >>              }
>> >>          }
>> >>
>> >> +        /* The lflow doesn't apply to the same set of datapaths
>> anymore,
>> >> so
>> >> +         * the dp group it is referencing is not the one it will be
>> synced
>> >> +         * with.  Drop the reference now, before any lflow of this
>> round
>> >> is
>> >> +         * synced: as long as the group is still referenced it stays
>> in
>> >> +         * 'dp_groups' and ovn_dp_group_create() refuses to modify
>> its SB
>> >> +         * row, inserting a new Logical_DP_Group row and deleting the
>> one
>> >> +         * that just became free instead of reusing it.
>> >> +         *
>> >> +         * This is the counterpart of the release done by
>> >> +         * do_ovn_lflow_add(), which covers the lflows that are
>> generated
>> >> +         * again.  An lflow that is only unlinked from one of its
>> >> lflow_refs
>> >> +         * and survives because other lflow_refs still reference it
>> never
>> >> +         * goes through do_ovn_lflow_add(). */
>> >> +        if (dpg_bitmap_changed && lflow->dpg) {
>> >> +            enum ovn_datapath_type dp_type =
>> >> +                ovn_stage_to_datapath_type(lflow->stage);
>> >> +            ovn_dp_group_release(&lflow_table->dp_groups[dp_type],
>> >> +                                 lflow->dpg);
>> >> +            lflow->dpg = NULL;
>> >> +        }
>> >> +
>> >>          lrn->linked = false;
>> >>      }
>> >>  }
>> >> @@ -690,7 +717,7 @@ lflow_ref_resync_flows(struct lflow_ref *lflow_ref,
>> >>                         const struct sbrec_logical_flow_table
>> >> *sbflow_table,
>> >>                         const struct sbrec_logical_dp_group_table
>> >> *dpgrp_table)
>> >>  {
>> >> -    lflow_ref_unlink_lflows(lflow_ref);
>> >> +    lflow_ref_unlink_lflows(lflow_ref, lflow_table);
>> >>      return lflow_ref_sync_lflows__(lflow_ref, lflow_table, ovnsb_txn,
>> >>                                     dps,
>> >>                                     ovn_internal_version_changed,
>> >> sbflow_table,
>> >> diff --git a/northd/lflow-mgr.h b/northd/lflow-mgr.h
>> >> index 84d0b3e67..6253be685 100644
>> >> --- a/northd/lflow-mgr.h
>> >> +++ b/northd/lflow-mgr.h
>> >> @@ -57,7 +57,7 @@ struct lflow_ref;
>> >>  struct lflow_ref *lflow_ref_create(void);
>> >>  void lflow_ref_destroy(struct lflow_ref *);
>> >>  void lflow_ref_clear(struct lflow_ref *lflow_ref);
>> >> -void lflow_ref_unlink_lflows(struct lflow_ref *);
>> >> +void lflow_ref_unlink_lflows(struct lflow_ref *, struct lflow_table
>> *);
>> >>  bool lflow_ref_resync_flows(struct lflow_ref *,
>> >>                              struct lflow_table *lflow_table,
>> >>                              struct ovsdb_idl_txn *ovnsb_txn,
>> >> diff --git a/northd/northd.c b/northd/northd.c
>> >> index 9f33b50cf..7753de970 100644
>> >> --- a/northd/northd.c
>> >> +++ b/northd/northd.c
>> >> @@ -20997,7 +20997,7 @@ lflow_handle_northd_lr_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>      HMAPX_FOR_EACH (hmapx_node, &tracked_lrs->crupdated) {
>> >>          struct ovn_datapath *od = hmapx_node->data;
>> >>
>> >> -        lflow_ref_unlink_lflows(od->datapath_lflows);
>> >> +        lflow_ref_unlink_lflows(od->datapath_lflows, lflows);
>> >>          build_lswitch_and_lrouter_iterate_by_lr(od, &lsi);
>> >>      }
>> >>
>> >> @@ -21052,7 +21052,7 @@ lflow_handle_northd_port_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>          /* Make sure 'op' is an lsp and not lrp. */
>> >>          ovs_assert(op->nbsp);
>> >>          /* Clear old lflows. */
>> >> -        lflow_ref_unlink_lflows(op->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(op->lflow_ref, lflows);
>> >>
>> >>          /* Generate new lflows. */
>> >>          struct ds match = DS_EMPTY_INITIALIZER;
>> >> @@ -21072,7 +21072,7 @@ lflow_handle_northd_port_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>          if (handled) {
>> >>              /* Now regenerate the stateful lflows for 'op' */
>> >>              /* Clear old lflows. */
>> >> -            lflow_ref_unlink_lflows(op->stateful_lflow_ref);
>> >> +            lflow_ref_unlink_lflows(op->stateful_lflow_ref, lflows);
>> >>              build_lbnat_lflows_iterate_by_lsp(op,
>> >>
>> >>  lflow_input->lr_stateful_table,
>> >>                                                &match, &actions,
>> lflows);
>> >> @@ -21164,7 +21164,7 @@ lflow_handle_northd_lb_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>          lb_dps = hmapx_node->data;
>> >>
>> >>          /* unlink old lflows. */
>> >> -        lflow_ref_unlink_lflows(lb_dps->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(lb_dps->lflow_ref, lflows);
>> >>
>> >>          /* Generate new lflows. */
>> >>          struct ds match = DS_EMPTY_INITIALIZER;
>> >> @@ -21220,7 +21220,7 @@ lflow_handle_lr_stateful_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>      HMAPX_FOR_EACH (hmapx_node, &trk_data->crupdated) {
>> >>          lr_stateful_rec = hmapx_node->data;
>> >>          /* Unlink old lflows. */
>> >> -        lflow_ref_unlink_lflows(lr_stateful_rec->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(lr_stateful_rec->lflow_ref, lflows);
>> >>
>> >>          /* Generate new lflows. */
>> >>          build_lr_stateful_flows(lr_stateful_rec,
>> >> lflow_input->lr_datapaths,
>> >> @@ -21245,7 +21245,7 @@ lflow_handle_lr_stateful_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>                                          lr_stateful_rec->lr_index);
>> >>          struct ovn_port *op;
>> >>          HMAP_FOR_EACH (op, dp_node, &od->ports) {
>> >> -            lflow_ref_unlink_lflows(op->stateful_lflow_ref);
>> >> +            lflow_ref_unlink_lflows(op->stateful_lflow_ref, lflows);
>> >>
>> >>              build_lbnat_lflows_iterate_by_lrp(op,
>> >>
>> >>  lflow_input->lr_stateful_table,
>> >> @@ -21265,7 +21265,7 @@ lflow_handle_lr_stateful_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>              }
>> >>
>> >>              if (op->peer && op->peer->nbsp) {
>> >> -                lflow_ref_unlink_lflows(op->peer->stateful_lflow_ref);
>> >> +                lflow_ref_unlink_lflows(op->peer->stateful_lflow_ref,
>> >> lflows);
>> >>
>> >>                  build_lbnat_lflows_iterate_by_lsp(
>> >>                      op->peer, lflow_input->lr_stateful_table, &match,
>> >> &actions,
>> >> @@ -21307,7 +21307,7 @@ lflow_handle_ls_stateful_changes(struct
>> >> ovsdb_idl_txn *ovnsb_txn,
>> >>          ovs_assert(od->nbs && uuid_equals(&od->nbs->header_.uuid,
>> >>
>> &ls_stateful_rec->nbs_uuid));
>> >>
>> >> -        lflow_ref_unlink_lflows(ls_stateful_rec->lflow_ref);
>> >> +        lflow_ref_unlink_lflows(ls_stateful_rec->lflow_ref, lflows);
>> >>
>> >>          /* Generate new lflows. */
>> >>          build_ls_stateful_flows(ls_stateful_rec, od,
>> >> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>> >> index 8c8d7852e..aa281c1a2 100644
>> >> --- a/tests/ovn-northd.at
>> >> +++ b/tests/ovn-northd.at
>> >> @@ -23647,3 +23647,97 @@ AT_CHECK([as northd ovn-appctl -t ovn-northd
>> >> inc-engine/enable-stopwatch nonexis
>> >>  OVN_CLEANUP_NORTHD
>> >>  AT_CLEANUP
>> >>  ])
>> >> +
>> >> +OVN_FOR_EACH_NORTHD_NO_HV([
>> >> +AT_SETUP([Datapath group reuse after an lflow loses a datapath])
>> >> +ovn_start
>> >> +
>> >> +# All four switches have ACLs, so the logical flows that only depend
>> on
>> >> +# "the switch has ACLs" are shared by the four of them.  ls1 and ls2
>> use
>> >> +# tier 0 while ls3 and ls4 use tier 1, which changes the actions of
>> the
>> >> +# egress "acl action" flows.  Hence three datapath groups are
>> expected:
>> >> +# {ls1, ls2}, {ls3, ls4} and {ls1, ls2, ls3, ls4}.
>> >> +check ovn-nbctl ls-add ls1
>> >> +check ovn-nbctl ls-add ls2
>> >> +check ovn-nbctl ls-add ls3
>> >> +check ovn-nbctl ls-add ls4
>> >> +check ovn-nbctl acl-add ls1 to-lport 1000 ip4 allow
>> >> +check ovn-nbctl acl-add ls2 to-lport 1000 ip6 allow
>> >> +check ovn-nbctl --tier=1 acl-add ls3 to-lport 1000 tcp allow
>> >> +check ovn-nbctl --wait=sb --tier=1 acl-add ls4 to-lport 1000 udp allow
>> >> +
>> >> +acl1=$(fetch_column nb:ACL _uuid match=ip4)
>> >> +check_row_count Logical_DP_Group 3
>> >> +
>> >> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> >> +
>> >> +# Move ls1's ACL to tier 1.  ls1 stops generating the egress "acl
>> action"
>> >> +# flows it shared with ls2, so those flows are left with a single
>> datapath
>> >> +# and the {ls1, ls2} datapath group becomes unused and is deleted.
>> northd
>> >> +# has to drop the reference it holds to that group, otherwise the
>> group is
>> >> +# leaked in the in-memory dp group table, still pointing to the SB row
>> >> that
>> >> +# has just been deleted.
>> >> +check ovn-nbctl --wait=sb set ACL $acl1 tier=1
>> >> +check_engine_stats lflow norecompute compute
>> >> +check_row_count Logical_DP_Group 2
>> >> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> >> +
>> >> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> >> +
>> >> +# Move ls1's ACL back to tier 0.  The {ls1, ls2} datapath group is
>> needed
>> >> +# again: a leaked group would be picked up here and northd would
>> complain
>> >> +# about its dangling SB reference.
>> >> +check ovn-nbctl --wait=sb set ACL $acl1 tier=0
>> >> +check_engine_stats lflow norecompute compute
>> >> +check_row_count Logical_DP_Group 3
>> >> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> >> +
>> >> +AT_CHECK([grep -q "logical_dp_group column is not set" \
>> >> +          northd/ovn-northd.log], [1])
>> >> +
>> >> +OVN_CLEANUP_NORTHD
>> >> +AT_CLEANUP
>> >> +])
>> >> +
>> >> +OVN_FOR_EACH_NORTHD_NO_HV([
>> >> +AT_SETUP([Datapath group SB row reuse when an lflow loses a datapath])
>> >> +ovn_start
>> >> +
>> >> +# ls1, ls2 and ls3 have tier 0 ACLs, ls4 has a tier 1 ACL.  The flows
>> that
>> >> +# only depend on "the switch has ACLs" are shared by the four of
>> them, and
>> >> +# the egress "acl action" flows of tier 0 are shared by ls1, ls2 and
>> ls3.
>> >> +# ls4 is the only user of the tier 1 flows, so those are synced with a
>> >> +# single datapath.  Hence two datapath groups: {ls1, ls2, ls3} and
>> >> +# {ls1, ls2, ls3, ls4}.
>> >> +check ovn-nbctl ls-add ls1
>> >> +check ovn-nbctl ls-add ls2
>> >> +check ovn-nbctl ls-add ls3
>> >> +check ovn-nbctl ls-add ls4
>> >> +check ovn-nbctl acl-add ls1 to-lport 1000 ip4 allow
>> >> +check ovn-nbctl acl-add ls2 to-lport 1000 ip6 allow
>> >> +check ovn-nbctl acl-add ls3 to-lport 1000 tcp allow
>> >> +check ovn-nbctl --wait=sb --tier=1 acl-add ls4 to-lport 1000 udp allow
>> >> +
>> >> +acl3=$(fetch_column nb:ACL _uuid match=tcp)
>> >> +check_row_count Logical_DP_Group 2
>> >> +ovn-sbctl --bare --columns _uuid list Logical_DP_Group | sort >
>> dpg_uuids
>> >> +
>> >> +check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
>> >> +
>> >> +# Move ls3's ACL to tier 1.  The tier 0 "acl action" flows are left
>> with
>> >> +# {ls1, ls2}: they are not generated again (ls1 and ls2 didn't
>> change),
>> >> they
>> >> +# are only unlinked from ls3's lflow_ref.  The {ls1, ls2, ls3} group
>> >> becomes
>> >> +# unused, so its SB row is free and northd is expected to modify it in
>> >> place
>> >> +# instead of inserting a new row and deleting this one.
>> >> +check ovn-nbctl --wait=sb set ACL $acl3 tier=1
>> >> +check_engine_stats lflow norecompute compute
>> >> +check_row_count Logical_DP_Group 3
>> >> +
>> >> +ovn-sbctl --bare --columns _uuid list Logical_DP_Group | sort >
>> dpg_uuids2
>> >> +AT_CHECK([comm -23 dpg_uuids dpg_uuids2], [0], [])
>> >> +CHECK_NO_CHANGE_AFTER_RECOMPUTE
>> >> +
>> >> +OVN_CLEANUP_NORTHD
>> >> +AT_CLEANUP
>> >> +])
>> >> +
>> >> --
>> >> 2.43.0
>> >>
>> >>
>> >> --
>> >>
>> >>
>> >>
>> >>
>> >> _'Esta mensagem é direcionada apenas para os endereços constantes no
>> >> cabeçalho inicial. Se você não está listado nos endereços constantes no
>> >> cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa
>> >> mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas
>> >> estão
>> >> imediatamente anuladas e proibidas'._
>> >>
>> >>
>> >> * **'Apesar do Magazine Luiza tomar
>> >> todas as precauções razoáveis para assegurar que nenhum vírus esteja
>> >> presente nesse e-mail, a empresa não poderá aceitar a responsabilidade
>> por
>> >> quaisquer perdas ou danos causados por esse e-mail ou por seus
>> anexos'.*
>> >>
>> >>
>> >>
>> >> _______________________________________________
>> >> dev mailing list
>> >> [email protected]
>> >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>> >>
>> >>
>> > _______________________________________________
>> > dev mailing list
>> > [email protected]
>> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>> >
>>
>>

-- 




_‘Esta mensagem é direcionada apenas para os endereços constantes no 
cabeçalho inicial. Se você não está listado nos endereços constantes no 
cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa 
mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão 
imediatamente anuladas e proibidas’._


* **‘Apesar do Magazine Luiza tomar 
todas as precauções razoáveis para assegurar que nenhum vírus esteja 
presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por 
quaisquer perdas ou danos causados por esse e-mail ou por seus anexos’.*



_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to