Hi Mark

Thanks for the review and the comments.

On Mon, Sep 25, 2023 at 9:48 PM Mark Michelson <mmich...@redhat.com> wrote:
>
> Hi Xavier,
>
> Functionality-wise, this looks good. I have a couple of small comments
> though.
>
> On 9/20/23 11:45, Xavier Simonart wrote:
> > Before this patch, if-status module handled pb->chassis and pb->up
> > for vif ports, but not for non-VIF ports.
> > This caused a few potential issues:
> > - It was difficult to check that a no-vif port has been previously claimed
> >    as there was no state in if-status. Hence it was difficult to always 
> > release
> >    such a port when pb->chassis was set to a different chassis.
> >    This issue will be fixed in a future patch.
> > - Releasing such ports caused ovn-controller to log warnings such as
> >    "Trying to delete unknown ports".
> > - If sb is readonly at the time of the claim, it forced the module to 
> > recompute.
> >
> > This patch fixed issues two and three by moving the work of setting 
> > pb->chassis
> > and pb->up to the if-status module.
> >
> > Signed-off-by: Xavier Simonart <xsimo...@redhat.com>
> >
> > ---
> > v2: Avoid clearing iface if already deleted
> > ---
> >   controller/binding.c        | 122 ++++++++++++++++++++++++---------
> >   controller/binding.h        |  18 +++++
> >   controller/if-status.c      | 130 ++++++++++++++++++++++++++++--------
> >   controller/if-status.h      |   9 ++-
> >   controller/ovn-controller.c |   6 +-
> >   tests/ovn.at                |  94 ++++++++++++++++++++++++++
> >   6 files changed, 318 insertions(+), 61 deletions(-)
> >
> > diff --git a/controller/binding.c b/controller/binding.c
> > index dbd2d52b7..92ca3ebbe 100644
> > --- a/controller/binding.c
> > +++ b/controller/binding.c
> > @@ -1200,7 +1200,7 @@ local_binding_set_pb(struct shash *local_bindings, 
> > const char *pb_name,
> >    *   Updates the 'pb->up' field only if it's explicitly set to 'false'.
> >    *   This is to ensure compatibility with older versions of ovn-northd.
> >    */
> > -static bool
> > +bool
> >   claimed_lport_set_up(const struct sbrec_port_binding *pb,
> >                        const struct sbrec_port_binding *parent_pb,
> >                        bool sb_readonly)
> > @@ -1213,6 +1213,8 @@ claimed_lport_set_up(const struct sbrec_port_binding 
> > *pb,
> >       if (!parent_pb || (parent_pb->n_up && parent_pb->up[0])) {
> >           if (!sb_readonly) {
> >               if (pb->n_up) {
> > +                VLOG_INFO("Setting lport %s up in Southbound",
> > +                          pb->logical_port);
> >                   sbrec_port_binding_set_up(pb, &up, 1);
> >               }
> >           } else if (pb->n_up && !pb->up[0]) {
> > @@ -1347,39 +1349,26 @@ claim_lport(const struct sbrec_port_binding *pb,
> >               }
> >               update_tracked = true;
> >
> > -            if (!notify_up) {
> > -                if (!claimed_lport_set_up(pb, parent_pb, sb_readonly)) {
> > -                    return false;
> > -                }
> > -                if (sb_readonly) {
> > -                    return false;
> > -                }
> > -                set_pb_chassis_in_sbrec(pb, chassis_rec, true);
> > -            } else {
> > -                if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, 
> > iface_rec,
> > -                                          sb_readonly, can_bind);
> > -            }
> > +            if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec,
> > +                                      sb_readonly, can_bind, notify_up,
> > +                                      parent_pb);
> >               register_claim_timestamp(pb->logical_port, now);
> >               sset_find_and_delete(postponed_ports, pb->logical_port);
> >           } else {
> > -            if (!notify_up) {
> > -                if (!claimed_lport_set_up(pb, parent_pb, sb_readonly)) {
> > -                    return false;
> > -                }
> > -            } else {
> > -                if ((pb->n_up && !pb->up[0]) ||
> > -                    !smap_get_bool(&iface_rec->external_ids,
> > -                                   OVN_INSTALLED_EXT_ID, false)) {
> > -                    if_status_mgr_claim_iface(if_mgr, pb, chassis_rec,
> > -                                              iface_rec, sb_readonly,
> > -                                              can_bind);
> > -                }
> > +            if ((pb->n_up && !pb->up[0]) ||
> > +                (notify_up && !smap_get_bool(&iface_rec->external_ids,
> > +                               OVN_INSTALLED_EXT_ID, false))) {
> > +                if_status_mgr_claim_iface(if_mgr, pb, chassis_rec,
> > +                                          iface_rec, sb_readonly,
> > +                                          can_bind, notify_up,
> > +                                          parent_pb);
> >               }
> >           }
> >       } else if (can_bind == CAN_BIND_AS_ADDITIONAL) {
> >           if (!is_additional_chassis(pb, chassis_rec)) {
> >               if_status_mgr_claim_iface(if_mgr, pb, chassis_rec, iface_rec,
> > -                                      sb_readonly, can_bind);
> > +                                      sb_readonly, can_bind, notify_up,
> > +                                      parent_pb);
> >               update_tracked = true;
> >           }
> >       }
> > @@ -2446,14 +2435,14 @@ consider_iface_release(const struct 
> > ovsrec_interface *iface_rec,
> >               remove_related_lport(b_lport->pb, b_ctx_out);
> >           }
> >
> > -        /* Clear the iface of the local binding. */
> > -        lbinding->iface = NULL;
> > -
> >           /* Check if the lbinding has children of type PB_CONTAINER.
> >            * If so, don't delete the local_binding. */
> >           if (!is_lbinding_container_parent(lbinding)) {
> >               local_binding_delete(lbinding, local_bindings, binding_lports,
> >                                    b_ctx_out->if_mgr);
> > +        } else {
> > +            /* Clear the iface of the local binding. */
> > +            lbinding->iface = NULL;
> >           }
> >       }
> >
> > @@ -3247,7 +3236,7 @@ local_binding_delete(struct local_binding *lbinding,
> >                        struct if_status_mgr *if_mgr)
> >   {
> >       shash_find_and_delete(local_bindings, lbinding->name);
> > -    if_status_mgr_delete_iface(if_mgr, lbinding->name);
> > +    if_status_mgr_delete_iface(if_mgr, lbinding->name, lbinding->iface);
> >       local_binding_destroy(lbinding, binding_lports);
> >   }
> >
> > @@ -3464,6 +3453,79 @@ port_binding_set_down(const struct sbrec_chassis 
> > *chassis_rec,
> >           }
> >   }
> >
> > +void
> > +port_binding_set_up(const struct sbrec_chassis *chassis_rec,
> > +                      const struct sbrec_port_binding_table *pb_table,
> > +                      const char *iface_id,
> > +                      const struct uuid *pb_uuid)
> > +{
> > +    const struct sbrec_port_binding *pb =
> > +        sbrec_port_binding_table_get_for_uuid(pb_table, pb_uuid);
> > +    if (!pb) {
> > +        VLOG_DBG("port_binding already deleted for %s", iface_id);
> > +        return;
> > +    }
> > +    if (pb->n_up && !pb->up[0]) {
> > +        bool up = true;
> > +        sbrec_port_binding_set_up(pb, &up, 1);
> > +        VLOG_INFO("Setting lport %s up in Southbound", pb->logical_port);
> > +        set_pb_chassis_in_sbrec(pb, chassis_rec, true);
> > +    }
> > +}
> > +
> > +void
> > +port_binding_set_pb(const struct sbrec_chassis *chassis_rec,
> > +                      const struct sbrec_port_binding_table *pb_table,
> > +                      const char *iface_id,
> > +                      const struct uuid *pb_uuid,
> > +                      enum can_bind bind_type)
> > +{
> > +    const struct sbrec_port_binding *pb =
> > +        sbrec_port_binding_table_get_for_uuid(pb_table, pb_uuid);
> > +    if (!pb) {
> > +        VLOG_DBG("port_binding already deleted for %s", iface_id);
> > +        return;
> > +    }
> > +    if (bind_type == CAN_BIND_AS_MAIN) {
> > +        set_pb_chassis_in_sbrec(pb, chassis_rec, true);
> > +    } else  if (bind_type == CAN_BIND_AS_ADDITIONAL) {
> > +        set_pb_additional_chassis_in_sbrec(pb, chassis_rec, true);
> > +    }
> > +}
> > +
> > +bool
> > +port_binding_pb_chassis_is_set(const struct sbrec_chassis *chassis_rec,
> > +                   const struct sbrec_port_binding_table *pb_table,
> > +                   const struct uuid *pb_uuid)
> > +{
> > +    const struct sbrec_port_binding *pb =
> > +        sbrec_port_binding_table_get_for_uuid(pb_table, pb_uuid);
> > +
> > +    if (pb && ((pb->chassis == chassis_rec) ||
> > +        is_additional_chassis(pb, chassis_rec))) {
> > +        return true;
> > +    }
> > +    return false;
> > +}
> > +
> > +bool
> > +port_binding_is_up(const struct sbrec_chassis *chassis_rec,
> > +                   const struct sbrec_port_binding_table *pb_table,
> > +                   const struct uuid *pb_uuid)
> > +{
> > +    const struct sbrec_port_binding *pb =
> > +        sbrec_port_binding_table_get_for_uuid(pb_table, pb_uuid);
> > +
> > +    if (!pb || pb->chassis != chassis_rec) {
> > +        return false;
> > +    }
> > +
> > +    if (pb->n_up && !pb->up[0]) {
> > +        return false;
> > +    }
> > +    return true;
> > +}
> > +
> >   static void
> >   binding_lport_set_up(struct binding_lport *b_lport, bool sb_readonly)
> >   {
> > diff --git a/controller/binding.h b/controller/binding.h
> > index 47df668a2..133badf3f 100644
> > --- a/controller/binding.h
> > +++ b/controller/binding.h
> > @@ -217,6 +217,18 @@ void port_binding_set_down(const struct sbrec_chassis 
> > *chassis_rec,
> >                              const struct sbrec_port_binding_table 
> > *pb_table,
> >                              const char *iface_id,
> >                              const struct uuid *pb_uuid);
> > +void port_binding_set_up(const struct sbrec_chassis *chassis_rec,
> > +                      const struct sbrec_port_binding_table *pb_table,
> > +                      const char *iface_id,
> > +                      const struct uuid *pb_uuid);
> > +void port_binding_set_pb(const struct sbrec_chassis *chassis_rec,
> > +                      const struct sbrec_port_binding_table *pb_table,
> > +                      const char *iface_id,
> > +                      const struct uuid *pb_uuid,
> > +                      enum can_bind bind_type);
> > +bool port_binding_pb_chassis_is_set(const struct sbrec_chassis 
> > *chassis_rec,
> > +                   const struct sbrec_port_binding_table *pb_table,
> > +                   const struct uuid *pb_uuid);
> >
> >   /* This structure represents a logical port (or port binding)
> >    * which is associated with 'struct local_binding'.
> > @@ -258,4 +270,10 @@ void update_qos(struct ovsdb_idl_index * 
> > sbrec_port_binding_by_name,
> >                   const struct ovsrec_open_vswitch_table *ovs_table,
> >                   const struct ovsrec_bridge_table *bridge_table);
> >
> > +bool claimed_lport_set_up(const struct sbrec_port_binding *pb,
> > +                     const struct sbrec_port_binding *parent_pb,
> > +                     bool sb_readonly);
> > +bool port_binding_is_up(const struct sbrec_chassis *chassis_rec,
> > +                   const struct sbrec_port_binding_table *pb_table,
> > +                   const struct uuid *pb_uuid);
> >   #endif /* controller/binding.h */
> > diff --git a/controller/if-status.c b/controller/if-status.c
> > index 6c5afc866..a907dbbaa 100644
> > --- a/controller/if-status.c
> > +++ b/controller/if-status.c
> > @@ -177,7 +177,9 @@ static const char *if_state_names[] = {
> >
> >   struct ovs_iface {
> >       char *id;               /* Extracted from OVS external_ids.iface_id. 
> > */
> > +    char *name;             /* OVS iface name. */
> >       struct uuid pb_uuid;    /* Port_binding uuid */
> > +    struct uuid parent_pb_uuid;    /* Port_binding uuid */
> >       enum if_state state;    /* State of the interface in the state 
> > machine. */
> >       uint32_t install_seqno; /* Seqno at which this interface is expected 
> > to
> >                                * be fully programmed in OVS.  Only used in 
> > state
> > @@ -185,6 +187,7 @@ struct ovs_iface {
> >                                */
> >       uint16_t mtu;           /* Extracted from OVS interface.mtu field. */
> >       enum can_bind bind_type;/* CAN_BIND_AS_MAIN or CAN_BIND_AS_ADDITIONAL 
> > */
> > +    bool notify_up;
>
> The following comment is in controller/binding.c::claimed_lport_set_up():
>
>      /* When notify_up is false in claim_port(), no state is created
>       * by if_status_mgr. In such cases, return false (i.e. trigger
> recompute)
>       * if we can't update sb (because it is readonly).
>       */
>
> It seems that now we create state in if_status_mgr for all types of
> ports, so this comment should be removed.
>
Yes, thanks. I'll send a v2.
>
> >   };
> >
> >   static uint64_t ifaces_usage;
> > @@ -224,6 +227,7 @@ static void if_status_mgr_update_bindings(
> >       struct if_status_mgr *mgr, struct local_binding_data *binding_data,
> >       const struct sbrec_chassis *,
> >       const struct ovsrec_interface_table *iface_table,
> > +    const struct sbrec_port_binding_table *pb_table,
> >       bool sb_readonly, bool ovs_readonly);
> >
> >   static void ovn_uninstall_hash_account_mem(const char *name, bool erase);
> > @@ -273,12 +277,22 @@ if_status_mgr_destroy(struct if_status_mgr *mgr)
> >       free(mgr);
> >   }
> >
> > +/* notify_up controls whether we wait for flows to be updated
> > + * before setting the interface up.
> > + * Non-VIF ports are reported up as soon as they are claimed
> > + * to maintain compatibility with older versions.
> > + * See aae25e6 binding: Correctly set Port_Binding.up for container/virtual
> > + * ports.
>
> Reading this comment didn't help me much, because it is not clear what
> the relationship is between "notify_up" and whether a port is vif or
> non-vif. Based on looking at the code, I *think* that notify_up is true
> for vif ports and false for non-vif ports, but I'm not 100% sure.
>
> Would it make more sense to name the struct field something like
> "is_vif" or something to make it more clear what the field means?
Yes, agreed. Will clarify in v2.
>
> > + */
> > +
> >   void
> >   if_status_mgr_claim_iface(struct if_status_mgr *mgr,
> >                             const struct sbrec_port_binding *pb,
> >                             const struct sbrec_chassis *chassis_rec,
> >                             const struct ovsrec_interface *iface_rec,
> > -                          bool sb_readonly, enum can_bind bind_type)
> > +                          bool sb_readonly, enum can_bind bind_type,
> > +                          bool notify_up,
> > +                          const struct sbrec_port_binding *parent_pb)
> >   {
> >       const char *iface_id = pb->logical_port;
> >       struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id);
> > @@ -287,8 +301,13 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr,
> >           iface = ovs_iface_create(mgr, iface_id, iface_rec, OIF_CLAIMED);
> >       }
> >       iface->bind_type = bind_type;
> > +    iface->notify_up = notify_up;
> >
> >       memcpy(&iface->pb_uuid, &pb->header_.uuid, sizeof(iface->pb_uuid));
> > +    if (parent_pb) {
> > +        memcpy(&iface->parent_pb_uuid, &parent_pb->header_.uuid,
> > +               sizeof(iface->pb_uuid));
> > +    }
> >       if (!sb_readonly) {
> >           if (bind_type == CAN_BIND_AS_MAIN) {
> >               set_pb_chassis_in_sbrec(pb, chassis_rec, true);
> > @@ -357,7 +376,8 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, 
> > const char *iface_id)
> >   }
> >
> >   void
> > -if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id)
> > +if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id,
> > +                           const struct ovsrec_interface *iface_rec)
> >   {
> >       struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id);
> >
> > @@ -365,6 +385,12 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, 
> > const char *iface_id)
> >           return;
> >       }
> >
> > +    if (iface_rec && strcmp(iface->name, iface_rec->name)) {
> > +        VLOG_DBG("Interface %s not deleted as port %s bound to %s",
> > +                 iface_rec->name, iface_id, iface->name);
> > +        return;
> > +    }
> > +
> >       switch (iface->state) {
> >       case OIF_CLAIMED:
> >       case OIF_INSTALL_FLOWS:
> > @@ -394,6 +420,7 @@ if_status_handle_claims(struct if_status_mgr *mgr,
> >                           struct local_binding_data *binding_data,
> >                           const struct sbrec_chassis *chassis_rec,
> >                           struct hmap *tracked_datapath,
> > +                        const struct sbrec_port_binding_table *pb_table,
> >                           bool sb_readonly)
> >   {
> >       if (!binding_data || sb_readonly) {
> > @@ -406,9 +433,15 @@ if_status_handle_claims(struct if_status_mgr *mgr,
> >       bool rc = false;
> >       HMAPX_FOR_EACH (node, &mgr->ifaces_per_state[OIF_CLAIMED]) {
> >           struct ovs_iface *iface = node->data;
> > -        VLOG_INFO("if_status_handle_claims for %s", iface->id);
> > -        local_binding_set_pb(bindings, iface->id, chassis_rec,
> > -                             tracked_datapath, true, iface->bind_type);
> > +        VLOG_INFO("if_status_handle_claims for %s, notify_up = %d", 
> > iface->id,
> > +                  iface->notify_up);
>
> This feels more like a VLOG_DBG level message than VLOG_INFO, especially
> with the "notify_up = %d" part added on.
>
> > +        if (iface->notify_up) {
> > +            local_binding_set_pb(bindings, iface->id, chassis_rec,
> > +                                 tracked_datapath, true, iface->bind_type);
> > +        } else {
> > +            port_binding_set_pb(chassis_rec, pb_table, iface->id,
> > +                                &iface->pb_uuid, iface->bind_type);
> > +        }
> >           rc = true;
> >       }
> >       return rc;
> > @@ -470,18 +503,32 @@ 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_bindings_pb_chassis_is_set(bindings, iface->id,
> > -            chassis_rec)) {
> > -            if (!sb_readonly) {
> > -                local_binding_set_pb(bindings, iface->id, chassis_rec,
> > -                                     NULL, true, iface->bind_type);
> > -            } else {
> > -                continue;
> > +        if (iface->notify_up) {
> > +            if (!local_bindings_pb_chassis_is_set(bindings, iface->id,
> > +                chassis_rec)) {
> > +                if (!sb_readonly) {
> > +                    local_binding_set_pb(bindings, iface->id, chassis_rec,
> > +                                         NULL, true, iface->bind_type);
> > +                } else {
> > +                    continue;
> > +                }
> > +            }
> > +            if (local_binding_is_up(bindings, iface->id, chassis_rec)) {
> > +                ovs_iface_set_state(mgr, iface, OIF_INSTALLED);
> > +            }
> > +        } else {
> > +            if (!port_binding_pb_chassis_is_set(chassis_rec, pb_table,
> > +                                                &iface->pb_uuid)) {
> > +                if (!sb_readonly) {
> > +                    port_binding_set_pb(chassis_rec, pb_table, iface->id,
> > +                                        &iface->pb_uuid, iface->bind_type);
> > +                } else {
> > +                    continue;
> > +                }
> > +            }
> > +            if (port_binding_is_up(chassis_rec, pb_table, 
> > &iface->pb_uuid)) {
> > +                ovs_iface_set_state(mgr, iface, OIF_INSTALLED);
> >               }
> > -        }
> > -        if (local_binding_is_up(bindings, iface->id, chassis_rec)) {
> > -            ovs_iface_set_state(mgr, iface, OIF_INSTALLED);
> >           }
> >       }
> >
> > @@ -528,9 +575,13 @@ if_status_mgr_update(struct if_status_mgr *mgr,
> >               /* No need to to update pb->chassis as already done
> >                * in if_status_handle_claims or if_status_mgr_claim_iface
> >                */
> > -            ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);
> > -            iface->install_seqno = mgr->iface_seqno + 1;
> > -            new_ifaces = true;
> > +            if (iface->notify_up) {
> > +                ovs_iface_set_state(mgr, iface, OIF_INSTALL_FLOWS);
> > +                iface->install_seqno = mgr->iface_seqno + 1;
> > +                new_ifaces = true;
> > +            } else {
> > +                ovs_iface_set_state(mgr, iface, OIF_MARK_UP);
> > +            }
> >           }
> >       } else {
> >           HMAPX_FOR_EACH_SAFE (node, &mgr->ifaces_per_state[OIF_CLAIMED]) {
> > @@ -587,6 +638,7 @@ if_status_mgr_run(struct if_status_mgr *mgr,
> >                     struct local_binding_data *binding_data,
> >                     const struct sbrec_chassis *chassis_rec,
> >                     const struct ovsrec_interface_table *iface_table,
> > +                  const struct sbrec_port_binding_table *pb_table,
> >                     bool sb_readonly, bool ovs_readonly)
> >   {
> >       struct ofctrl_acked_seqnos *acked_seqnos =
> > @@ -622,15 +674,18 @@ if_status_mgr_run(struct if_status_mgr *mgr,
> >
> >       /* Update binding states. */
> >       if_status_mgr_update_bindings(mgr, binding_data, chassis_rec,
> > -                                  iface_table,
> > +                                  iface_table, pb_table,
> >                                     sb_readonly, ovs_readonly);
> >   }
> >
> >   static void
> > -ovs_iface_account_mem(const char *iface_id, bool erase)
> > +ovs_iface_account_mem(const char *iface_id, char *iface_name, bool erase)
> >   {
> >       uint32_t size = (strlen(iface_id) + sizeof(struct ovs_iface) +
> >                        sizeof(struct shash_node));
> > +    if (iface_name) {
> > +        size += strlen(iface_name);
> > +    }
> >       if (erase) {
> >           ifaces_usage -= size;
> >       } else {
> > @@ -682,12 +737,18 @@ ovs_iface_create(struct if_status_mgr *mgr, const 
> > char *iface_id,
> >   {
> >       struct ovs_iface *iface = xzalloc(sizeof *iface);
> >
> > -    VLOG_DBG("Interface %s create.", iface_id);
> > +    VLOG_DBG("Interface %s create for iface %s.", iface_id,
> > +             iface_rec ? iface_rec->name : "");
> >       iface->id = xstrdup(iface_id);
> >       shash_add_nocopy(&mgr->ifaces, iface->id, iface);
> >       ovs_iface_set_state(mgr, iface, state);
> > -    ovs_iface_account_mem(iface_id, false);
> > -    if_status_mgr_iface_update(mgr, iface_rec);
> > +    if (iface_rec) {
> > +        ovs_iface_account_mem(iface_id, iface_rec->name, false);
> > +        if_status_mgr_iface_update(mgr, iface_rec);
> > +        iface->name = xstrdup(iface_rec->name);
> > +    } else {
> > +        ovs_iface_account_mem(iface_id, NULL, false);
> > +    }
> >       return iface;
> >   }
> >
> > @@ -711,7 +772,8 @@ ovs_iface_destroy(struct if_status_mgr *mgr, struct 
> > ovs_iface *iface)
> >       if (node) {
> >           shash_steal(&mgr->ifaces, node);
> >       }
> > -    ovs_iface_account_mem(iface->id, true);
> > +    ovs_iface_account_mem(iface->id, iface->name, true);
> > +    free(iface->name);
> >       free(iface->id);
> >       free(iface);
> >   }
> > @@ -752,6 +814,7 @@ if_status_mgr_update_bindings(struct if_status_mgr *mgr,
> >                                 struct local_binding_data *binding_data,
> >                                 const struct sbrec_chassis *chassis_rec,
> >                                 const struct ovsrec_interface_table 
> > *iface_table,
> > +                              const struct sbrec_port_binding_table 
> > *pb_table,
> >                                 bool sb_readonly, bool ovs_readonly)
> >   {
> >       if (!binding_data) {
> > @@ -788,9 +851,20 @@ 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;
> > -
> > -        local_binding_set_up(bindings, iface->id, chassis_rec, ts_now_str,
> > -                             sb_readonly, ovs_readonly);
> > +        if (iface->notify_up) {
> > +            local_binding_set_up(bindings, iface->id, chassis_rec, 
> > ts_now_str,
> > +                                 sb_readonly, ovs_readonly);
> > +        } else if (!sb_readonly) {
> > +            const struct sbrec_port_binding *pb =
> > +                sbrec_port_binding_table_get_for_uuid(pb_table,
> > +                                                      &iface->pb_uuid);
> > +            if (pb) {
> > +                const struct sbrec_port_binding *parent_pb =
> > +                    sbrec_port_binding_table_get_for_uuid(pb_table,
> > +                                                  &iface->parent_pb_uuid);
> > +                claimed_lport_set_up(pb, parent_pb, sb_readonly);
> > +            }
> > +        }
> >       }
> >       free(ts_now_str);
> >
> > diff --git a/controller/if-status.h b/controller/if-status.h
> > index 9714f6d8d..4ae5ad481 100644
> > --- a/controller/if-status.h
> > +++ b/controller/if-status.h
> > @@ -32,9 +32,12 @@ void if_status_mgr_claim_iface(struct if_status_mgr *,
> >                                  const struct sbrec_port_binding *pb,
> >                                  const struct sbrec_chassis *chassis_rec,
> >                                  const struct ovsrec_interface *iface_rec,
> > -                               bool sb_readonly, enum can_bind bind_type);
> > +                               bool sb_readonly, enum can_bind bind_type,
> > +                               bool notify_up,
> > +                               const struct sbrec_port_binding *parent_pb);
> >   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_delete_iface(struct if_status_mgr *, const char 
> > *iface_id,
> > +                                const struct ovsrec_interface *iface_rec);
> >
> >   void if_status_mgr_update(struct if_status_mgr *, struct 
> > local_binding_data *,
> >                             const struct sbrec_chassis *chassis,
> > @@ -45,6 +48,7 @@ void if_status_mgr_update(struct if_status_mgr *, struct 
> > local_binding_data *,
> >   void if_status_mgr_run(struct if_status_mgr *mgr, struct 
> > local_binding_data *,
> >                          const struct sbrec_chassis *,
> >                          const struct ovsrec_interface_table *iface_table,
> > +                       const struct sbrec_port_binding_table *pb_table,
> >                          bool sb_readonly, bool ovs_readonly);
> >   void if_status_mgr_get_memory_usage(struct if_status_mgr *mgr,
> >                                       struct simap *usage);
> > @@ -54,6 +58,7 @@ bool if_status_handle_claims(struct if_status_mgr *mgr,
> >                                struct local_binding_data *binding_data,
> >                                const struct sbrec_chassis *chassis_rec,
> >                                struct hmap *tracked_datapath,
> > +                             const struct sbrec_port_binding_table 
> > *pb_table,
> >                                bool sb_readonly);
> >   void if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr,
> >                                           const char *name,
> > diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> > index 859d9cab9..b09ac047e 100644
> > --- a/controller/ovn-controller.c
> > +++ b/controller/ovn-controller.c
> > @@ -1815,6 +1815,8 @@ runtime_data_sb_ro_handler(struct engine_node *node, 
> > void *data)
> >           engine_ovsdb_node_get_index(
> >                   engine_get_input("SB_chassis", node),
> >                   "name");
> > +    const struct sbrec_port_binding_table *pb_table =
> > +        EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
> >
> >       if (chassis_id) {
> >           chassis = chassis_lookup_by_name(sbrec_chassis_by_name, 
> > chassis_id);
> > @@ -1829,7 +1831,7 @@ runtime_data_sb_ro_handler(struct engine_node *node, 
> > void *data)
> >                                       &rt_data->lbinding_data,
> >                                       chassis,
> >                                       &rt_data->tracked_dp_bindings,
> > -                                    sb_readonly)) {
> > +                                    pb_table, sb_readonly)) {
> >               engine_set_node_state(node, EN_UPDATED);
> >               rt_data->tracked = true;
> >           }
> > @@ -5871,6 +5873,8 @@ main(int argc, char *argv[])
> >                       if_status_mgr_run(if_mgr, binding_data, chassis,
> >                                         ovsrec_interface_table_get(
> >                                                     ovs_idl_loop.idl),
> > +                                      sbrec_port_binding_table_get(
> > +                                                 ovnsb_idl_loop.idl),
> >                                         !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 ba5ce298a..b4f146590 100644
> > --- a/tests/ovn.at
> > +++ b/tests/ovn.at
> > @@ -37004,3 +37004,97 @@ AT_CHECK([grep -c "NXT_CT_FLUSH_ZONE" 
> > hv1/ovs-vswitchd.log], [0], [dnl
> >   OVN_CLEANUP([hv1])
> >   AT_CLEANUP
> >   ])
> > +
> > +OVN_FOR_EACH_NORTHD([
> > +AT_SETUP([virtual port claim race condition])
> > +AT_KEYWORDS([virtual ports])
> > +ovn_start
> > +
> > +send_garp() {
> > +    local hv=$1 inport=$2 eth_src=$3 eth_dst=$4 spa=$5 tpa=$6
> > +    local 
> > request=${eth_dst}${eth_src}08060001080006040001${eth_src}${spa}${eth_dst}${tpa}
>
> Can this be changed to use fmt_pkt()? It makes understanding and
> debugging tests much easier. Don't forget to add an AT_SKIP to the test
> if HAVE_SCAPY is false.
I'd prefer to have a separate patch for this: looking at the whole
test, we have 6 implementations of send_garp, all very similar but
slightly different.
A separate patch could clean them all. WDYT?

>
> > +    as hv$hv ovs-appctl netdev-dummy/receive hv${hv}-vif$inport $request
> > +}
> > +
> > +net_add n1
> > +
> > +sim_add hv1
> > +as hv1
> > +ovs-vsctl add-br br-phys
> > +ovn_attach n1 br-phys 192.168.0.1
> > +ovn-appctl vlog/set dbg
> > +ovs-vsctl -- add-port br-int hv1-vif1 -- \
> > +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
> > +    options:tx_pcap=hv1/vif1-tx.pcap \
> > +    options:rxq_pcap=hv1/vif1-rx.pcap \
> > +    ofport-request=1
> > +ovs-vsctl -- add-port br-int hv1-vif3 -- \
> > +    set interface hv1-vif3 \
> > +    options:tx_pcap=hv1/vif3-tx.pcap \
> > +    options:rxq_pcap=hv1/vif3-rx.pcap \
> > +    ofport-request=3
> > +
> > +ovs-appctl -t ovn-controller vlog/set dbg
> > +
> > +ovn-nbctl ls-add sw0
> > +
> > +check ovn-nbctl lsp-add sw0 sw0-vir
> > +check ovn-nbctl lsp-set-addresses sw0-vir "50:54:00:00:00:10 10.0.0.10"
> > +check ovn-nbctl lsp-set-port-security sw0-vir "50:54:00:00:00:10 10.0.0.10"
> > +check ovn-nbctl lsp-set-type sw0-vir virtual
> > +check ovn-nbctl set logical_switch_port sw0-vir 
> > options:virtual-ip=10.0.0.10
> > +check ovn-nbctl set logical_switch_port sw0-vir 
> > options:virtual-parents=sw0-p1
> > +
> > +check ovn-nbctl lsp-add sw0 sw0-p1
> > +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:00:00:00:03 10.0.0.3 
> > 1000::3"
> > +check ovn-nbctl lsp-set-port-security sw0-p1 "50:54:00:00:00:03 10.0.0.3 
> > 10.0.0.10 1000::3"
> > +
> > +# Create a logical router and attach both logical switches
> > +check ovn-nbctl lr-add lr0
> > +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 
> > 1000::a/64
> > +check ovn-nbctl lsp-add sw0 sw0-lr0
> > +check ovn-nbctl lsp-set-type sw0-lr0 router
> > +check ovn-nbctl lsp-set-addresses sw0-lr0 00:00:00:00:ff:01
> > +check ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0
> > +
> > +wait_for_ports_up
> > +ovn-nbctl --wait=hv sync
> > +hv1_ch_uuid=`ovn-sbctl --bare --columns _uuid find chassis name="hv1"`
> > +
> > +# Try to bind sw0-vir directly to an OVS port. This should be ignored by
> > +# ovn-controller.
> > +as hv1 ovs-vsctl set interface hv1-vif3 external-ids:iface-id=sw0-vir
> > +
> > +# Make sb to sleep, so that claim of sw0-vir (through pinctrl) and 
> > hv1-vif3 can be handled within same idl by controller
> > +sleep_sb
> > +
> > +# From sw0-p0 send GARP for 10.0.0.10. hv1 should claim sw0-vir
> > +# and sw0-p1 should be its virtual_parent.
> > +eth_src=505400000003
> > +eth_dst=ffffffffffff
> > +spa=$(ip_to_hex 10 0 0 10)
> > +tpa=$(ip_to_hex 10 0 0 10)
> > +send_garp 1 1 $eth_src $eth_dst $spa $tpa
> > +
> > +OVS_WAIT_UNTIL([test 1 = `cat hv1/ovn-controller.log | grep "pinctrl 
> > received  packet-in" | \
> > +grep opcode=BIND_VPORT | grep OF_Table_ID=29 | wc -l`])
> > +
> > +sleep_controller hv1
> > +
> > +# Cleanup hv1-vif3. This should not interfere with sw0-vir claim
> > +as hv1 ovs-vsctl del-port hv1-vif3
> > +
> > +wake_up_sb
> > +ovn-nbctl --wait=sb sync
> > +wake_up_controller hv1
> > +check ovn-nbctl --wait=hv sync
> > +
> > +wait_row_count Port_Binding 1 logical_port=sw0-vir chassis=$hv1_ch_uuid
> > +check_row_count Port_Binding 1 logical_port=sw0-vir virtual_parent=sw0-p1
> > +wait_for_ports_up sw0-vir
> > +check ovn-nbctl --wait=hv sync
> > +
> > +OVN_CLEANUP([hv1])
> > +AT_CLEANUP
> > +])
> > +
>
Thanks
Xavier

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

Reply via email to