Hi Xavier,

On 5/12/22 11:04, Xavier Simonart wrote:
> When VIF ports are claimed on a chassis, SBDB Port_Binding table is updated.
> If the SBDB IDL is still is read-only ("in transaction") when such a update
> is required, the update is not possible and recompute is triggered through
> I+P failure.
> 
> This situation can happen:
> - after updating Port_Binding->chassis to SBDB for one port, in a following
>   iteration, ovn-controller handles Interface:external_ids:ovn-installed
>   (for the same port) while SBDB is still read-only.
> - after updating Port_Binding->chassis to SBDB for one port, in a following
>   iteration, ovn-controller updates Port_Binding->chassis for another port,
>   while SBDB is still read-only.
> 
> This patch prevent the recompute, by having the if-status module
> updating the Port_Binding chassis (if needed), when possible.
> This does not delay Port_Binding chassis update compared to before this
> patch: Port_Binding chassis will be updated as soon as SBDB is again
> writable, as it was the case, through a recompute, before this patch.

Just to confirm, with your patch the Port_Binding chassis will be
updated when the SBDB is again writable and will *not* cause a
recompute, right?

> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2059253
> Signed-off-by: Xavier Simonart <[email protected]>
> ---
>  controller/binding.c        | 124 ++++++++++++++++++++++++++----------
>  controller/binding.h        |   9 ++-
>  controller/if-status.c      |  31 +++++++--
>  controller/if-status.h      |   6 +-
>  controller/ovn-controller.c |   6 +-
>  tests/ovn.at                |  55 +++++++++++++++-
>  6 files changed, 184 insertions(+), 47 deletions(-)
> 
> diff --git a/controller/binding.c b/controller/binding.c
> index e5ba56b25..d917d8775 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -657,11 +657,15 @@ local_binding_get_lport_ofport(const struct shash 
> *local_bindings,
>  }
>  
>  bool
> -local_binding_is_up(struct shash *local_bindings, const char *pb_name)
> +local_binding_is_up(struct shash *local_bindings, const char *pb_name,
> +                    const struct sbrec_chassis *chassis_rec)
>  {
>      struct local_binding *lbinding =
>          local_binding_find(local_bindings, pb_name);
>      struct binding_lport *b_lport = 
> local_binding_get_primary_lport(lbinding);
> +    if (b_lport && b_lport->pb->chassis != chassis_rec) {
> +        return false;
> +    }
>      if (lbinding && b_lport && lbinding->iface) {
>          if (b_lport->pb->n_up && !b_lport->pb->up[0]) {
>              return false;
> @@ -673,13 +677,23 @@ local_binding_is_up(struct shash *local_bindings, const 
> char *pb_name)
>  }
>  
>  bool
> -local_binding_is_down(struct shash *local_bindings, const char *pb_name)
> +local_binding_is_down(struct shash *local_bindings, const char *pb_name,
> +                      const struct sbrec_chassis *chassis_rec)
>  {
>      struct local_binding *lbinding =
>          local_binding_find(local_bindings, pb_name);
>  
>      struct binding_lport *b_lport = 
> local_binding_get_primary_lport(lbinding);
>  
> +    if (b_lport) {
> +        if (b_lport->pb->chassis == chassis_rec) {
> +            return false;
> +        } else if (b_lport->pb->chassis) {
> +            VLOG_DBG("lport %s already claimed by other chassis",
> +                     b_lport->pb->logical_port);
> +        }
> +    }
> +
>      if (!lbinding) {
>          return true;
>      }
> @@ -894,6 +908,48 @@ get_lport_type_str(enum en_lport_type lport_type)
>      OVS_NOT_REACHED();
>  }
>  
> +static void set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb,

Nit: this should be:

static void
set_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb,

> +                          const struct sbrec_chassis *chassis_rec)
> +{
> +    if (pb->chassis != chassis_rec) {
> +        if (pb->chassis) {
> +            VLOG_INFO("Changing chassis for lport %s from %s to %s.",
> +                    pb->logical_port, pb->chassis->name,
> +                    chassis_rec->name);

Nit: indentation.

> +        } else {
> +            VLOG_INFO("Claiming lport %s for this chassis.", 
> pb->logical_port);
> +        }
> +        for (int i = 0; i < pb->n_mac; i++) {
> +            VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]);
> +        }
> +        sbrec_port_binding_set_chassis(pb, chassis_rec);
> +    }
> +}
> +
> +static void clear_pb_chassis_in_sbrec(const struct sbrec_port_binding *pb)

Here too, the function name should start on a new line.

> +{
> +    if (pb->chassis) {
> +        sbrec_port_binding_set_chassis(pb, NULL);
> +    }
> +}
> +
> +void
> +local_binding_set_pb(struct shash *local_bindings, const char *pb_name,
> +                    const struct sbrec_chassis *chassis_rec)

Nit: indentation.

> +{
> +    struct local_binding *lbinding =
> +        local_binding_find(local_bindings, pb_name);
> +    struct binding_lport *b_lport = 
> local_binding_get_primary_lport(lbinding);
> +
> +    if (b_lport) {
> +        if (chassis_rec) {
> +            set_pb_chassis_in_sbrec(b_lport->pb, chassis_rec);
> +        } else {
> +            clear_pb_chassis_in_sbrec(b_lport->pb);
> +        }
> +    }
> +}
> +
>  /* For newly claimed ports, if 'notify_up' is 'false':
>   * - set the 'pb.up' field to true if 'pb' has no 'parent_pb'.
>   * - set the 'pb.up' field to true if 'parent_pb.up' is 'true' (e.g., for
> @@ -906,23 +962,37 @@ get_lport_type_str(enum en_lport_type lport_type)
>   *   it's explicitly set to 'false'.
>   *   This is to ensure compatibility with older versions of ovn-northd.
>   */
> -static void
> +static bool
>  claimed_lport_set_up(const struct sbrec_port_binding *pb,
>                       const struct sbrec_port_binding *parent_pb,
>                       const struct sbrec_chassis *chassis_rec,
> -                     bool notify_up, struct if_status_mgr *if_mgr)
> +                     bool notify_up, struct if_status_mgr *if_mgr,
> +                     bool sb_readonly)
>  {
> +

Extra line not needed.

>      if (!notify_up) {
>          bool up = true;
>          if (!parent_pb || (parent_pb->n_up && parent_pb->up[0])) {
> -            sbrec_port_binding_set_up(pb, &up, 1);
> +            if (!sb_readonly) {
> +                sbrec_port_binding_set_up(pb, &up, 1);
> +            } else if (pb->n_up && !pb->up[0]) {
> +                return false;
> +            }
>          }
> -        return;
> +        if (sb_readonly && (pb->chassis != chassis_rec)) {
> +            /* Handle the cases where if_status_mgr does not claim the
> +             * interface.In those cases, if we do not set pb->chassis in sb
> +             * now (as readonly), we might not do it later ...
> +             */
> +            return false;
> +        }
> +        return true;
>      }
>  
>      if (pb->chassis != chassis_rec || (pb->n_up && !pb->up[0])) {
>          if_status_mgr_claim_iface(if_mgr, pb->logical_port);
>      }
> +    return true;
>  }
>  
>  /* Returns false if lport is not claimed due to 'sb_readonly'.
> @@ -937,27 +1007,15 @@ claim_lport(const struct sbrec_port_binding *pb,
>              struct hmap *tracked_datapaths,
>              struct if_status_mgr *if_mgr)
>  {
> -    if (!sb_readonly) {
> -        claimed_lport_set_up(pb, parent_pb, chassis_rec, notify_up, if_mgr);
> -    }
>  
> +    if (!claimed_lport_set_up(pb, parent_pb, chassis_rec, notify_up,
> +           if_mgr, sb_readonly)) {
> +        return false;
> +    }
>      if (pb->chassis != chassis_rec) {
> -        if (sb_readonly) {
> -            return false;
> -        }
> -
> -        if (pb->chassis) {
> -            VLOG_INFO("Changing chassis for lport %s from %s to %s.",
> -                    pb->logical_port, pb->chassis->name,
> -                    chassis_rec->name);
> -        } else {
> -            VLOG_INFO("Claiming lport %s for this chassis.", 
> pb->logical_port);
> +        if (!sb_readonly) {
> +            set_pb_chassis_in_sbrec(pb, chassis_rec);
>          }
> -        for (int i = 0; i < pb->n_mac; i++) {
> -            VLOG_INFO("%s: Claiming %s", pb->logical_port, pb->mac[i]);
> -        }
> -
> -        sbrec_port_binding_set_chassis(pb, chassis_rec);
>  
>          if (tracked_datapaths) {
>              update_lport_tracking(pb, tracked_datapaths, true);
> @@ -974,7 +1032,6 @@ claim_lport(const struct sbrec_port_binding *pb,
>          }
>          sbrec_port_binding_set_encap(pb, encap_rec);
>      }
> -

Unrelated?

>      return true;
>  }
>  
> @@ -986,7 +1043,8 @@ claim_lport(const struct sbrec_port_binding *pb,
>   * Caller should make sure that this is the case.
>   */
>  static bool
> -release_lport_(const struct sbrec_port_binding *pb, bool sb_readonly)
> +release_lport_(const struct sbrec_port_binding *pb, bool sb_readonly,
> +               struct if_status_mgr *if_mgr)
>  {
>      if (pb->encap) {
>          if (sb_readonly) {
> @@ -995,11 +1053,13 @@ release_lport_(const struct sbrec_port_binding *pb, 
> bool sb_readonly)
>          sbrec_port_binding_set_encap(pb, NULL);
>      }
>  
> +    /* if sb readonly, pb->chassis unset through if-status if present */
>      if (pb->chassis) {
> -        if (sb_readonly) {
> +        if (!sb_readonly) {
> +            sbrec_port_binding_set_chassis(pb, NULL);
> +        } else if (!if_status_mgr_iface_is_present(if_mgr, 
> pb->logical_port)) {
>              return false;
>          }
> -        sbrec_port_binding_set_chassis(pb, NULL);
>      }
>  
>      if (pb->virtual_parent) {
> @@ -1009,7 +1069,8 @@ release_lport_(const struct sbrec_port_binding *pb, 
> bool sb_readonly)
>          sbrec_port_binding_set_virtual_parent(pb, NULL);
>      }
>  
> -    VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port);
> +    VLOG_INFO("Releasing lport %s from this chassis (sb_readonly=%d)",
> +              pb->logical_port, sb_readonly);
>      return true;
>  }
>  
> @@ -1017,7 +1078,7 @@ static bool
>  release_lport(const struct sbrec_port_binding *pb, bool sb_readonly,
>                struct hmap *tracked_datapaths, struct if_status_mgr *if_mgr)
>  {
> -    if (!release_lport_(pb, sb_readonly)) {
> +    if (!release_lport_(pb, sb_readonly, if_mgr)) {
>          return false;
>      }
>  
> @@ -1342,10 +1403,9 @@ consider_localport(const struct sbrec_port_binding *pb,
>      /* If the port binding is claimed, then release it as localport is 
> claimed
>       * by any ovn-controller. */
>      if (pb->chassis == b_ctx_in->chassis_rec) {
> -        if (!release_lport_(pb, !b_ctx_in->ovnsb_idl_txn)) {
> +        if (!release_lport_(pb, !b_ctx_in->ovnsb_idl_txn, 
> b_ctx_out->if_mgr)) {
>              return false;
>          }
> -

Unrelated?

>          remove_related_lport(pb, b_ctx_out);
>      }
>  
> diff --git a/controller/binding.h b/controller/binding.h
> index 430a8d9b1..45202a321 100644
> --- a/controller/binding.h
> +++ b/controller/binding.h
> @@ -151,14 +151,17 @@ const struct sbrec_port_binding 
> *local_binding_get_primary_pb(
>  ofp_port_t local_binding_get_lport_ofport(const struct shash *local_bindings,
>                                            const char *pb_name);
>  
> -bool local_binding_is_up(struct shash *local_bindings, const char *pb_name);
> -bool local_binding_is_down(struct shash *local_bindings, const char 
> *pb_name);
> +bool local_binding_is_up(struct shash *local_bindings, const char *pb_name,
> +                         const struct sbrec_chassis *);
> +bool local_binding_is_down(struct shash *local_bindings, const char *pb_name,
> +                         const struct sbrec_chassis *);
>  void local_binding_set_up(struct shash *local_bindings, const char *pb_name,
>                            const char *ts_now_str, bool sb_readonly,
>                            bool ovs_readonly);
>  void local_binding_set_down(struct shash *local_bindings, const char 
> *pb_name,
>                              bool sb_readonly, bool ovs_readonly);
> -
> +void local_binding_set_pb(struct shash *local_bindings, const char *pb_name,
> +                         const struct sbrec_chassis *chassis_rec);
>  void binding_register_ovs_idl(struct ovsdb_idl *);
>  void binding_run(struct binding_ctx_in *, struct binding_ctx_out *);
>  bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> diff --git a/controller/if-status.c b/controller/if-status.c
> index dbdf8b66f..e36df22a0 100644
> --- a/controller/if-status.c
> +++ b/controller/if-status.c
> @@ -115,6 +115,7 @@ static void ovs_iface_set_state(struct if_status_mgr *, 
> struct ovs_iface *,
>  
>  static void if_status_mgr_update_bindings(
>      struct if_status_mgr *mgr, struct local_binding_data *binding_data,
> +    const struct sbrec_chassis *chassis_rec,
>      bool sb_readonly, bool ovs_readonly);
>  
>  struct if_status_mgr *
> @@ -181,6 +182,13 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr, 
> const char *iface_id)
>      }
>  }
>  
> +bool
> +if_status_mgr_iface_is_present(struct if_status_mgr *mgr, const char 
> *iface_id)
> +{
> +    struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id);
> +    return (!!iface);
> +}
> +
>  void
>  if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id)
>  {
> @@ -247,7 +255,8 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, 
> const char *iface_id)
>  
>  void
>  if_status_mgr_update(struct if_status_mgr *mgr,
> -                     struct local_binding_data *binding_data)
> +                     struct local_binding_data *binding_data,
> +                     const struct sbrec_chassis *chassis_rec)
>  {
>      if (!binding_data) {
>          return;
> @@ -262,7 +271,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
>      HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_MARK_UP]) {
>          struct ovs_iface *iface = node->data;
>  
> -        if (local_binding_is_up(bindings, iface->id)) {
> +        if (local_binding_is_up(bindings, iface->id, chassis_rec)) {
>              ovs_iface_set_state(mgr, iface, OIF_INSTALLED);
>          }
>      }
> @@ -273,7 +282,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
>      HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_MARK_DOWN]) {
>          struct ovs_iface *iface = node->data;
>  
> -        if (local_binding_is_down(bindings, iface->id)) {
> +        if (local_binding_is_down(bindings, iface->id, chassis_rec)) {
>              ovs_iface_destroy(mgr, iface);
>          }
>      }
> @@ -306,6 +315,7 @@ if_status_mgr_update(struct if_status_mgr *mgr,
>  void
>  if_status_mgr_run(struct if_status_mgr *mgr,
>                    struct local_binding_data *binding_data,
> +                  const struct sbrec_chassis *chassis_rec,
>                    bool sb_readonly, bool ovs_readonly)
>  {
>      struct ofctrl_acked_seqnos *acked_seqnos =
> @@ -328,8 +338,8 @@ if_status_mgr_run(struct if_status_mgr *mgr,
>      ofctrl_acked_seqnos_destroy(acked_seqnos);
>  
>      /* Update binding states. */
> -    if_status_mgr_update_bindings(mgr, binding_data, sb_readonly,
> -                                  ovs_readonly);
> +    if_status_mgr_update_bindings(mgr, binding_data, chassis_rec,
> +                                  sb_readonly, ovs_readonly);
>  }
>  
>  static void
> @@ -390,6 +400,7 @@ ovs_iface_set_state(struct if_status_mgr *mgr, struct 
> ovs_iface *iface,
>  static void
>  if_status_mgr_update_bindings(struct if_status_mgr *mgr,
>                                struct local_binding_data *binding_data,
> +                              const struct sbrec_chassis *chassis_rec,
>                                bool sb_readonly, bool ovs_readonly)
>  {
>      if (!binding_data) {
> @@ -404,6 +415,9 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr,
>       */
>      HMAPX_FOR_EACH (node, &mgr->ifaces_per_state[OIF_INSTALL_FLOWS]) {
>          struct ovs_iface *iface = node->data;
> +        if (!sb_readonly) {
> +            local_binding_set_pb(bindings, iface->id, chassis_rec);
> +        }
>  
>          local_binding_set_down(bindings, iface->id, sb_readonly, 
> ovs_readonly);
>      }
> @@ -415,7 +429,9 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr,
>      char *ts_now_str = xasprintf("%lld", time_wall_msec());
>      HMAPX_FOR_EACH (node, &mgr->ifaces_per_state[OIF_MARK_UP]) {
>          struct ovs_iface *iface = node->data;
> -
> +        if (!sb_readonly) {
> +            local_binding_set_pb(bindings, iface->id, chassis_rec);
> +        }
>          local_binding_set_up(bindings, iface->id, ts_now_str,
>                               sb_readonly, ovs_readonly);
>      }
> @@ -426,6 +442,9 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr,
>       */
>      HMAPX_FOR_EACH (node, &mgr->ifaces_per_state[OIF_MARK_DOWN]) {
>          struct ovs_iface *iface = node->data;
> +        if (!sb_readonly) {
> +            local_binding_set_pb(bindings, iface->id, NULL);
> +        }
>  
>          local_binding_set_down(bindings, iface->id, sb_readonly, 
> ovs_readonly);
>      }
> diff --git a/controller/if-status.h b/controller/if-status.h
> index ff4aa760e..2c55eb18e 100644
> --- a/controller/if-status.h
> +++ b/controller/if-status.h
> @@ -31,10 +31,14 @@ void if_status_mgr_claim_iface(struct if_status_mgr *, 
> const char *iface_id);
>  void if_status_mgr_release_iface(struct if_status_mgr *, const char 
> *iface_id);
>  void if_status_mgr_delete_iface(struct if_status_mgr *, const char 
> *iface_id);
>  
> -void if_status_mgr_update(struct if_status_mgr *, struct local_binding_data 
> *);
> +void if_status_mgr_update(struct if_status_mgr *, struct local_binding_data 
> *,
> +                          const struct sbrec_chassis *chassis);
>  void if_status_mgr_run(struct if_status_mgr *mgr, struct local_binding_data 
> *,
> +                       const struct sbrec_chassis *chassis,
>                         bool sb_readonly, bool ovs_readonly);
>  void if_status_mgr_get_memory_usage(struct if_status_mgr *mgr,
>                                      struct simap *usage);
> +bool if_status_mgr_iface_is_present(struct if_status_mgr *mgr,
> +                                    const char *iface_id);
>  
>  # endif /* controller/if-status.h */
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 5a6274eb2..994aebdfb 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -3912,7 +3912,7 @@ main(int argc, char *argv[])
>                          runtime_data ? &runtime_data->lbinding_data : NULL;
>                      stopwatch_start(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME,
>                                      time_msec());
> -                    if_status_mgr_update(if_mgr, binding_data);
> +                    if_status_mgr_update(if_mgr, binding_data, chassis);
>                      stopwatch_stop(IF_STATUS_MGR_UPDATE_STOPWATCH_NAME,
>                                     time_msec());
>  
> @@ -3938,8 +3938,8 @@ main(int argc, char *argv[])
>                                     time_msec());
>                      stopwatch_start(IF_STATUS_MGR_RUN_STOPWATCH_NAME,
>                                      time_msec());
> -                    if_status_mgr_run(if_mgr, binding_data, !ovnsb_idl_txn,
> -                                      !ovs_idl_txn);
> +                    if_status_mgr_run(if_mgr, binding_data, chassis,
> +                                      !ovnsb_idl_txn, !ovs_idl_txn);
>                      stopwatch_stop(IF_STATUS_MGR_RUN_STOPWATCH_NAME,
>                                     time_msec());
>                  }
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 6a0a169c1..403fbc85f 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -13934,6 +13934,7 @@ ovn_attach n1 br-phys 192.168.0.11
>  ovs-vsctl -- add-port br-int hv1-vif0 -- \
>  set Interface hv1-vif0 ofport-request=1
>  
> +

Unrelated?

>  sim_add hv2
>  as hv2
>  ovs-vsctl add-br br-phys
> @@ -13983,7 +13984,10 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int 
> table=65 | grep actions=output:1],
>  echo "verifying that lsp0 binding moves when requested-chassis is changed"
>  
>  ovn-nbctl lsp-set-options lsp0 requested-chassis=hv2
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" 
> hv1/ovn-controller.log)])
> +
> +# We might see multiple "Releasing lport ...", when sb is read only
> +OVS_WAIT_UNTIL([test 1 -le $(grep -c "Releasing lport lsp0 from this 
> chassis" hv1/ovn-controller.log)])
> +
>  wait_column "$hv2_uuid" Port_Binding chassis logical_port=lsp0
>  
>  # (6) Chassis hv2 should add flows and hv1 should not.
> @@ -14029,7 +14033,7 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 
> | grep in_port=1], [0], [ig
>  AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=65 | grep 
> actions=output:1], [0], [ignore])
>  
>  check ovn-nbctl --wait=hv lsp-set-options lsp0 
> requested-chassis=non-existant-chassis
> -OVS_WAIT_UNTIL([test 1 = $(grep -c "Releasing lport lsp0 from this chassis" 
> hv1/ovn-controller.log)])
> +OVS_WAIT_UNTIL([test 1 -le $(grep -c "Releasing lport lsp0 from this 
> chassis" hv1/ovn-controller.log)])
>  check ovn-nbctl --wait=hv sync
>  wait_column '' Port_Binding chasssi logical_port=lsp0
>  AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=0 | grep in_port=1], [1], 
> [])
> @@ -30595,3 +30599,50 @@ test_mac_binding_flows hv2 00\:00\:00\:00\:10\:10 1
>  OVN_CLEANUP([hv1], [hv2])
>  AT_CLEANUP
>  ])
> +
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([recomputes])
> +ovn_start
> +
> +# Add chassis
> +net_add n1
> +sim_add hv1
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +
> +add_switch_ports() {
> +    for port in $(seq $1 $2); do
> +        logical_switch_port=lsp${port}
> +        check ovn-nbctl lsp-add ls1 $logical_switch_port
> +        check ovn-nbctl lsp-set-addresses $logical_switch_port dynamic
> +
> +        as hv1 ovs-vsctl \
> +            -- add-port br-int vif${port} \
> +            -- set Interface vif${port} 
> external_ids:iface-id=$logical_switch_port
> +    done

Don't we need a wait_for_ports_up here to make sure the new ports are
claimed and processed?

> +
> +    check ovn-nbctl --wait=hv sync
> +    AT_CHECK([test $(ovn-appctl -t ovn-controller coverage/read-counter 
> lflow_run) == $lflow_run])
> +}
> +
> +check ovn-nbctl ls-add ls1
> +check ovn-nbctl set Logical_Switch ls1 other_config:subnet=10.1.0.0/16
> +check ovn-nbctl set Logical_Switch ls1 other_config:exclude_ips=10.1.255.254
> +
> +check ovn-nbctl lr-add lr1
> +check ovn-nbctl lsp-add ls1 lsp0 -- set Logical_Switch_Port lsp0 type=router 
> options:router-port=lrp0 addresses=dynamic
> +check ovn-nbctl lrp-add lr1 lrp0 "f0:00:00:01:00:01" 10.1.255.254/16
> +check ovn-nbctl lr-nat-add lr1 snat 10.2.0.1 10.1.0.0/16
> +
> +check ovn-nbctl --wait=hv sync
> +lflow_run=$(ovn-appctl -t ovn-controller coverage/read-counter lflow_run)
> +
> +add_switch_ports 1 50
> +add_switch_ports 51 100
> +add_switch_ports 101 150
> +
> +OVN_CLEANUP([hv1])
> +AT_CLEANUP
> +])

Thanks,
Dumitru

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

Reply via email to