On Wed, Oct 25, 2023 at 2:52 PM Ilya Maximets <i.maxim...@ovn.org> wrote:

> On 10/18/23 09:56, Ales Musil wrote:
> > Make sure that if any zone limit was set via DB
> > all zones are forced to be set there also. This
> > is done by tracking which datapath has zone limit
> > protection and it is reflected in the dpctl command.
> >
> > If the datapath is protected the dpctl command will
> > return permission error.
> >
> > Signed-off-by: Ales Musil <amu...@redhat.com>
> > ---
> > v5: Rebase on top of current master.
> >     Address comments from Ilya:
> >     - Add more user friendly error message to the dpctl.
> >     - Fix style related problems.
> > v4: Rebase on top of current master.
> >     Make the protection datapath wide.
> > ---
> >  lib/ct-dpif.c              | 27 +++++++++++++++++++++++++++
> >  lib/ct-dpif.h              |  2 ++
> >  lib/dpctl.c                | 12 ++++++++++++
> >  ofproto/ofproto-dpif.c     | 14 ++++++++++++++
> >  ofproto/ofproto-provider.h |  5 +++++
> >  ofproto/ofproto.c          | 11 +++++++++++
> >  ofproto/ofproto.h          |  2 ++
> >  tests/system-traffic.at    | 36 ++++++++++++++++++++++++++++++++++++
> >  vswitchd/bridge.c          |  7 +++++++
> >  9 files changed, 116 insertions(+)
> >
> > diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
> > index 2ee045164..41d2dc4d7 100644
> > --- a/lib/ct-dpif.c
> > +++ b/lib/ct-dpif.c
> > @@ -23,6 +23,7 @@
> >  #include "openvswitch/ofp-ct.h"
> >  #include "openvswitch/ofp-parse.h"
> >  #include "openvswitch/vlog.h"
> > +#include "sset.h"
> >
> >  VLOG_DEFINE_THIS_MODULE(ct_dpif);
> >
> > @@ -32,6 +33,10 @@ struct flags {
> >      const char *name;
> >  };
> >
> > +/* Protection for CT zone limit per datapath. */
> > +static struct sset ct_limit_protection =
> > +        SSET_INITIALIZER(&ct_limit_protection);
> > +
> >  static void ct_dpif_format_counters(struct ds *,
> >                                      const struct ct_dpif_counters *);
> >  static void ct_dpif_format_timestamp(struct ds *,
> > @@ -1064,3 +1069,25 @@ ct_dpif_get_features(struct dpif *dpif, enum
> ct_features *features)
> >              ? dpif->dpif_class->ct_get_features(dpif, features)
> >              : EOPNOTSUPP);
> >  }
> > +
> > +void
> > +ct_dpif_set_zone_limit_protection(struct dpif *dpif, bool protected)
> > +{
> > +    if (sset_contains(&ct_limit_protection, dpif->full_name) ==
> protected) {
> > +        return;
> > +    }
> > +
> > +    if (protected) {
> > +        sset_add(&ct_limit_protection, dpif->full_name);
> > +    } else {
> > +        sset_find_and_delete(&ct_limit_protection, dpif->full_name);
> > +    }
> > +    VLOG_INFO("The CT zone limit protection is %s for \"%s\".",
> > +              protected ? "enabled" : "disabled", dpif->full_name);
>
> This message is only useful for users who already use dpctl.
> And they will see the error while trying to use it.  I don't
> think we need this message in the log file.
>
> > +}
> > +
> > +bool
> > +ct_dpif_is_zone_limit_protected(struct dpif *dpif)
> > +{
> > +    return sset_contains(&ct_limit_protection, dpif->full_name);
> > +}
> > diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
> > index c8a7c155e..c3786d5ae 100644
> > --- a/lib/ct-dpif.h
> > +++ b/lib/ct-dpif.h
> > @@ -350,5 +350,7 @@ int ct_dpif_get_timeout_policy_name(struct dpif
> *dpif, uint32_t tp_id,
> >                                      uint16_t dl_type, uint8_t nw_proto,
> >                                      char **tp_name, bool *is_generic);
> >  int ct_dpif_get_features(struct dpif *dpif, enum ct_features *features);
> > +void ct_dpif_set_zone_limit_protection(struct dpif *, bool protected);
> > +bool ct_dpif_is_zone_limit_protected(struct dpif *);
> >
> >  #endif /* CT_DPIF_H */
> > diff --git a/lib/dpctl.c b/lib/dpctl.c
> > index a8c654747..8c87ff9e8 100644
> > --- a/lib/dpctl.c
> > +++ b/lib/dpctl.c
> > @@ -2234,6 +2234,12 @@ dpctl_ct_set_limits(int argc, const char *argv[],
> >          ct_dpif_push_zone_limit(&zone_limits, zone, limit, 0);
> >      }
> >
> > +    if (ct_dpif_is_zone_limit_protected(dpif)) {
> > +        ds_put_cstr(&ds, "the zone limits are set via DB");
>
> I'd suggest something more user-friendly, e.g. "The zone limits are set
> via database, use 'ovs-vsctl set-zone-limit <...>' instead."
>
> > +        error = EPERM;
> > +        goto error;
> > +    }
> > +
> >      error = ct_dpif_set_limits(dpif, &zone_limits);
> >      if (!error) {
> >          ct_dpif_free_zone_limits(&zone_limits);
> > @@ -2310,6 +2316,12 @@ dpctl_ct_del_limits(int argc, const char *argv[],
> >          }
> >      }
> >
> > +    if (ct_dpif_is_zone_limit_protected(dpif)) {
> > +        ds_put_cstr(&ds, "the zone limits are set via DB");
>
> The same here, but with 'del-zone-limit'.
>
> > +        error = EPERM;
> > +        goto error;
> > +    }
> > +
> >      error = ct_dpif_del_limits(dpif, &zone_limits);
> >      if (!error) {
> >          goto out;
> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > index 6a931a806..7c5360b67 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -5663,6 +5663,19 @@ ct_zone_limits_commit(struct dpif_backer *backer)
> >      }
> >  }
> >
> > +static void
> > +ct_zone_limit_protection_update(const char *datapath_type, bool
> protected)
> > +{
> > +    struct dpif_backer *backer = shash_find_data(&all_dpif_backers,
> > +                                                 datapath_type);
> > +    if (!backer) {
> > +        return;
> > +    }
> > +
> > +    ct_dpif_set_zone_limit_protection(backer->dpif, protected);
> > +}
> > +
> > +
>
> Too many empty lines.
>
> >  static void
> >  get_datapath_cap(const char *datapath_type, struct smap *cap)
> >  {
> > @@ -6953,4 +6966,5 @@ const struct ofproto_class ofproto_dpif_class = {
> >      ct_set_zone_timeout_policy,
> >      ct_del_zone_timeout_policy,
> >      ct_zone_limit_update,
> > +    ct_zone_limit_protection_update,
> >  };
> > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> > index 33fb99280..e1d72b6df 100644
> > --- a/ofproto/ofproto-provider.h
> > +++ b/ofproto/ofproto-provider.h
> > @@ -1925,6 +1925,11 @@ struct ofproto_class {
> >      /* Updates the CT zone limit for specified zone. */
> >      void (*ct_zone_limit_update)(const char *dp_type, int32_t zone,
> >                                   int64_t *limit);
> > +
> > +    /* Sets the CT zone limit protection to "protected" for the
> specified
> > +     * datapath type. */
> > +    void (*ct_zone_limit_protection_update)(const char *dp_type,
> > +                                            bool protected);
> >  };
> >
> >  extern const struct ofproto_class ofproto_dpif_class;
> > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> > index 649add089..122a06f30 100644
> > --- a/ofproto/ofproto.c
> > +++ b/ofproto/ofproto.c
> > @@ -1038,6 +1038,17 @@ ofproto_ct_zone_limit_update(const char
> *datapath_type, int32_t zone_id,
> >      }
> >  }
> >
> > +void
> > +ofproto_ct_zone_limit_protection_update(const char *datapath_type,
> > +                                        bool protected)
> > +{
> > +    datapath_type = ofproto_normalize_type(datapath_type);
> > +    const struct ofproto_class *class =
> ofproto_class_find__(datapath_type);
> > +
> > +    if (class && class->ct_zone_limit_protection_update) {
> > +        class->ct_zone_limit_protection_update(datapath_type,
> protected);
> > +    }
> > +}
> >
> >  /* Spanning Tree Protocol (STP) configuration. */
> >
> > diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
> > index 7ce6a65e1..1c07df275 100644
> > --- a/ofproto/ofproto.h
> > +++ b/ofproto/ofproto.h
> > @@ -386,6 +386,8 @@ void ofproto_ct_del_zone_timeout_policy(const char
> *datapath_type,
> >                                          uint16_t zone);
> >  void ofproto_ct_zone_limit_update(const char *datapath_type, int32_t
> zone_id,
> >                                    int64_t *limit);
> > +void ofproto_ct_zone_limit_protection_update(const char *datapath_type,
> > +                                             bool protected);
> >  void ofproto_get_datapath_cap(const char *datapath_type,
> >                                struct smap *dp_cap);
> >
> > diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> > index 445a9ffbd..df5c7f3d7 100644
> > --- a/tests/system-traffic.at
> > +++ b/tests/system-traffic.at
> > @@ -5275,6 +5275,42 @@ OVS_WAIT_UNTIL_EQUAL([ovs-appctl
> dpctl/ct-get-limits], [dnl
> >  default limit=0
> >  zone=0,limit=3,count=0])
> >
> > +dnl Try to overwrite the zone limit via dpctl command.
> > +AT_CHECK([ovs-appctl dpctl/ct-set-limits default=15 zone=3,limit=5
> zone=0,limit=5], [2], [ignore], [ignore])
>
> Would be better to not ignore the error message.
> Same for tests below.
>
> > +
> > +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl
> > +default limit=0
> > +zone=0,limit=3,count=0
> > +])
> > +
> > +AT_CHECK([ovs-appctl dpctl/ct-del-limits zone=0], [2], [ignore],
> [ignore])
> > +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl
> > +default limit=0
> > +zone=0,limit=3,count=0
> > +])
> > +
> > +AT_CHECK([ovs-vsctl del-zone-limit $DP_TYPE zone=0])
> > +AT_CHECK([ovs-vsctl set-zone-limit $DP_TYPE default limit=10])
> > +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl
> > +default limit=10
> > +])
> > +
> > +AT_CHECK([ovs-appctl dpctl/ct-set-limits default=15 zone=1,limit=5],
> [2], [ignore], [ignore])
> > +
> > +dnl Delete all zones from DB, that should remove the protection.
> > +AT_CHECK([ovs-vsctl del-zone-limit $DP_TYPE default])
> > +
> > +AT_CHECK([ovs-appctl dpctl/ct-set-limits default=15 zone=1,limit=5])
> > +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl
> > +default limit=15
> > +zone=1,limit=5,count=0
> > +])
> > +
> > +AT_CHECK([ovs-appctl dpctl/ct-del-limits zone=1])
> > +AT_CHECK([ovs-appctl dpctl/ct-get-limits], [0], [dnl
> > +default limit=15
> > +])
> > +
> >  OVS_TRAFFIC_VSWITCHD_STOP(["dnl
> >  /could not create datapath/d
> >  /(Cannot allocate memory) on packet/d"])
> > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> > index 4545556b5..0fe348a77 100644
> > --- a/vswitchd/bridge.c
> > +++ b/vswitchd/bridge.c
> > @@ -739,6 +739,7 @@ datapath_destroy(struct datapath *dp)
> >                                           NULL);
> >          }
> >
> > +        ofproto_ct_zone_limit_protection_update(dp->type, false);
> >          hmap_remove(&all_datapaths, &dp->node);
> >          hmap_destroy(&dp->ct_zones);
> >          free(dp->type);
> > @@ -751,6 +752,7 @@ static void
> >  ct_zones_reconfigure(struct datapath *dp, struct ovsrec_datapath
> *dp_cfg)
> >  {
> >      struct ct_zone *ct_zone;
> > +    bool protected = false;
> >
> >      /* Add new 'ct_zone's or update existing 'ct_zone's based on the
> database
> >       * state. */
> > @@ -784,6 +786,8 @@ ct_zones_reconfigure(struct datapath *dp, struct
> ovsrec_datapath *dp_cfg)
> >          }
> >
> >          ct_zone->last_used = idl_seqno;
> > +
> > +        protected = protected || !!zone_cfg->limit;
> >      }
> >
> >      /* Purge 'ct_zone's no longer found in the database. */
> > @@ -804,6 +808,9 @@ ct_zones_reconfigure(struct datapath *dp, struct
> ovsrec_datapath *dp_cfg)
> >          dp->ct_default_limit = default_limit;
> >      }
> >
> > +    protected = protected || !!dp_cfg->ct_zone_default_limit;
> > +
> > +    ofproto_ct_zone_limit_protection_update(dp->type, protected);
> >  }
> >
> >  static void
>
>
Thank you for the review, all should be addressed in v6.

Thanks,
Ales

-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to