FWIW I think this is the right choice given the options.  May be worth
adding a comment in the actual code as to why we can't just execute
the rule and have to queue it instead.

Acked-by: Ethan Jackson <et...@nicira.com>


On Tue, Sep 10, 2013 at 10:27 PM, Ben Pfaff <b...@nicira.com> wrote:
> This is the first step toward making a global lock that protects everything
> needed for updating the flow table.  This commit starts out by merging one
> lock into the new one, and later commits will continue that process.
>
> The mutex is initially a recursive one, because I wasn't sure that there
> were no nested acquisitions at this stage, but a later commit will change
> it to a regular error-checking mutex once it's settled down a bit.
>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  ofproto/ofproto-dpif.c     |    4 ++--
>  ofproto/ofproto-provider.h |   17 ++++++++---------
>  ofproto/ofproto.c          |   23 ++++++++++++++---------
>  3 files changed, 24 insertions(+), 20 deletions(-)
>
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index eab5533..2e2f571 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -3636,12 +3636,12 @@ expire(struct dpif_backer *backer)
>
>          /* Expire OpenFlow flows whose idle_timeout or hard_timeout
>           * has passed. */
> -        ovs_mutex_lock(&ofproto->up.expirable_mutex);
> +        ovs_mutex_lock(&ofproto_mutex);
>          LIST_FOR_EACH_SAFE (rule, next_rule, expirable,
>                              &ofproto->up.expirable) {
>              rule_expire(rule_dpif_cast(rule));
>          }
> -        ovs_mutex_unlock(&ofproto->up.expirable_mutex);
> +        ovs_mutex_unlock(&ofproto_mutex);
>
>          /* All outstanding data in existing flows has been accounted, so 
> it's a
>           * good time to do bond rebalancing. */
> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> index d23ff9c..edc9abc 100644
> --- a/ofproto/ofproto-provider.h
> +++ b/ofproto/ofproto-provider.h
> @@ -40,6 +40,8 @@ struct ofputil_flow_mod;
>  struct bfd_cfg;
>  struct meter;
>
> +extern struct ovs_mutex ofproto_mutex;
> +
>  /* An OpenFlow switch.
>   *
>   * With few exceptions, ofproto implementations may look at these fields but
> @@ -77,11 +79,8 @@ struct ofproto {
>
>      struct hindex cookies;      /* Rules indexed on their cookie values. */
>
> -    /* Optimisation for flow expiry.
> -     * These flows should all be present in tables. */
> -    struct ovs_mutex expirable_mutex;
> -    struct list expirable OVS_GUARDED; /* Expirable 'struct rule"s in all
> -                                          tables. */
> +    /* List of expirable flows, in all flow tables. */
> +    struct list expirable OVS_GUARDED_BY(ofproto_mutex);
>
>      /* Meter table.
>       * OpenFlow meters start at 1.  To avoid confusion we leave the first
> @@ -270,9 +269,9 @@ struct rule {
>      uint64_t add_seqno;         /* Sequence number when added. */
>      uint64_t modify_seqno;      /* Sequence number when changed. */
>
> -    /* Optimisation for flow expiry. */
> -    struct list expirable;      /* In ofproto's 'expirable' list if this rule
> -                                 * is expirable, otherwise empty. */
> +    /* Optimisation for flow expiry.  In ofproto's 'expirable' list if this
> +     * rule is expirable, otherwise empty. */
> +    struct list expirable OVS_GUARDED_BY(ofproto_mutex);
>  };
>
>  void ofproto_rule_ref(struct rule *);
> @@ -325,7 +324,7 @@ void ofproto_rule_delete(struct ofproto *, struct 
> classifier *cls,
>                           struct rule *) OVS_REQ_WRLOCK(cls->rwlock);
>  void ofproto_rule_reduce_timeouts(struct rule *rule, uint16_t idle_timeout,
>                                    uint16_t hard_timeout)
> -    OVS_EXCLUDED(rule->ofproto->expirable_mutex, rule->timeout_mutex);
> +    OVS_EXCLUDED(ofproto_mutex, rule->timeout_mutex);
>
>  bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t out_port);
>
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index 10c803c..9e33684 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -245,6 +245,8 @@ static const struct ofproto_class **ofproto_classes;
>  static size_t n_ofproto_classes;
>  static size_t allocated_ofproto_classes;
>
> +struct ovs_mutex ofproto_mutex;
> +
>  unsigned flow_eviction_threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT;
>  unsigned n_handler_threads;
>  enum ofproto_flow_miss_model flow_miss_model = OFPROTO_HANDLE_MISS_AUTO;
> @@ -275,6 +277,8 @@ ofproto_init(const struct shash *iface_hints)
>      struct shash_node *node;
>      size_t i;
>
> +    ovs_mutex_init_recursive(&ofproto_mutex);
> +
>      ofproto_class_register(&ofproto_dpif_class);
>
>      /* Make a local copy, since we don't own 'iface_hints' elements. */
> @@ -430,6 +434,7 @@ ofproto_create(const char *datapath_name, const char 
> *datapath_type,
>      }
>
>      /* Initialize. */
> +    ovs_mutex_lock(&ofproto_mutex);
>      memset(ofproto, 0, sizeof *ofproto);
>      ofproto->ofproto_class = class;
>      ofproto->name = xstrdup(datapath_name);
> @@ -454,7 +459,6 @@ ofproto_create(const char *datapath_name, const char 
> *datapath_type,
>      ofproto->n_tables = 0;
>      hindex_init(&ofproto->cookies);
>      list_init(&ofproto->expirable);
> -    ovs_mutex_init_recursive(&ofproto->expirable_mutex);
>      ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name);
>      ofproto->state = S_OPENFLOW;
>      list_init(&ofproto->pending);
> @@ -470,6 +474,7 @@ ofproto_create(const char *datapath_name, const char 
> *datapath_type,
>      ofproto->min_mtu = INT_MAX;
>      ovs_rwlock_init(&ofproto->groups_rwlock);
>      hmap_init(&ofproto->groups);
> +    ovs_mutex_unlock(&ofproto_mutex);
>
>      error = ofproto->ofproto_class->construct(ofproto);
>      if (error) {
> @@ -1194,7 +1199,7 @@ ofproto_destroy__(struct ofproto *ofproto)
>
>      free(ofproto->vlan_bitmap);
>
> -    ovs_mutex_destroy(&ofproto->expirable_mutex);
> +    ovs_mutex_destroy(&ofproto_mutex);
>      ofproto->ofproto_class->dealloc(ofproto);
>  }
>
> @@ -3991,17 +3996,17 @@ reduce_timeout(uint16_t max, uint16_t *timeout)
>  void
>  ofproto_rule_reduce_timeouts(struct rule *rule,
>                               uint16_t idle_timeout, uint16_t hard_timeout)
> -    OVS_EXCLUDED(rule->ofproto->expirable_mutex, rule->timeout_mutex)
> +    OVS_EXCLUDED(ofproto_mutex, rule->timeout_mutex)
>  {
>      if (!idle_timeout && !hard_timeout) {
>          return;
>      }
>
> -    ovs_mutex_lock(&rule->ofproto->expirable_mutex);
> +    ovs_mutex_lock(&ofproto_mutex);
>      if (list_is_empty(&rule->expirable)) {
>          list_insert(&rule->ofproto->expirable, &rule->expirable);
>      }
> -    ovs_mutex_unlock(&rule->ofproto->expirable_mutex);
> +    ovs_mutex_unlock(&ofproto_mutex);
>
>      ovs_mutex_lock(&rule->timeout_mutex);
>      reduce_timeout(idle_timeout, &rule->idle_timeout);
> @@ -6202,11 +6207,11 @@ oftable_remove_rule__(struct ofproto *ofproto, struct 
> classifier *cls,
>      classifier_remove(cls, &rule->cr);
>      cookies_remove(ofproto, rule);
>      eviction_group_remove_rule(rule);
> -    ovs_mutex_lock(&ofproto->expirable_mutex);
> +    ovs_mutex_lock(&ofproto_mutex);
>      if (!list_is_empty(&rule->expirable)) {
>          list_remove(&rule->expirable);
>      }
> -    ovs_mutex_unlock(&ofproto->expirable_mutex);
> +    ovs_mutex_unlock(&ofproto_mutex);
>      if (!list_is_empty(&rule->meter_list_node)) {
>          list_remove(&rule->meter_list_node);
>          list_init(&rule->meter_list_node);
> @@ -6239,9 +6244,9 @@ oftable_insert_rule(struct rule *rule)
>      ovs_mutex_unlock(&rule->timeout_mutex);
>
>      if (may_expire) {
> -        ovs_mutex_lock(&ofproto->expirable_mutex);
> +        ovs_mutex_lock(&ofproto_mutex);
>          list_insert(&ofproto->expirable, &rule->expirable);
> -        ovs_mutex_unlock(&ofproto->expirable_mutex);
> +        ovs_mutex_unlock(&ofproto_mutex);
>      }
>      cookies_insert(ofproto, rule);
>
> --
> 1.7.10.4
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to