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

On Fri, Oct 11, 2013 at 12:23 AM, Ben Pfaff <b...@nicira.com> wrote:
> 'ofproto_mutex' has effectively protected the monitor-related members of
> struct ofconn since its introduction, but this was not written down or
> systematically annotated.  This commit makes it more systematic and fixes
> a few issues found using the annotations.
>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  ofproto/connmgr.c |   62 
> +++++++++++++++++++++++++++++++++++++++++++----------
>  ofproto/connmgr.h |   17 +++++++++------
>  ofproto/ofproto.c |    4 ++--
>  3 files changed, 64 insertions(+), 19 deletions(-)
>
> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
> index d6233e0..ba5a171 100644
> --- a/ofproto/connmgr.c
> +++ b/ofproto/connmgr.c
> @@ -52,7 +52,8 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 
> 5);
>   *
>   * 'ofproto_mutex' must be held whenever an ofconn is created or destroyed 
> or,
>   * more or less equivalently, whenever an ofconn is added to or removed from 
> a
> - * connmgr.  'ofproto_mutex' doesn't protect the data inside the ofconn. */
> + * connmgr.  'ofproto_mutex' doesn't protect the data inside the ofconn, 
> except
> + * as specifically noted below. */
>  struct ofconn {
>  /* Configuration that persists from one connection to the next. */
>
> @@ -98,12 +99,36 @@ struct ofconn {
>      uint32_t master_async_config[OAM_N_TYPES]; /* master, other */
>      uint32_t slave_async_config[OAM_N_TYPES];  /* slave */
>
> -    /* Flow monitors. */
> -    struct hmap monitors;       /* Contains "struct ofmonitor"s. */
> -    struct list updates;        /* List of "struct ofpbuf"s. */
> -    bool sent_abbrev_update;    /* Does 'updates' contain NXFME_ABBREV? */
> -    struct rconn_packet_counter *monitor_counter;
> -    uint64_t monitor_paused;
> +/* Flow monitors (e.g. NXST_FLOW_MONITOR). */
> +
> +    /* Configuration.  Contains "struct ofmonitor"s. */
> +    struct hmap monitors OVS_GUARDED_BY(ofproto_mutex);
> +
> +    /* Flow control.
> +     *
> +     * When too many flow monitor notifications back up in the transmit 
> buffer,
> +     * we pause the transmission of further notifications.  These members 
> track
> +     * the flow control state.
> +     *
> +     * When notifications are flowing, 'monitor_paused' is 0.  When
> +     * notifications are paused, 'monitor_paused' is the value of
> +     * 'monitor_seqno' at the point we paused.
> +     *
> +     * 'monitor_counter' counts the OpenFlow messages and bytes currently in
> +     * flight.  This value growing too large triggers pausing. */
> +    uint64_t monitor_paused OVS_GUARDED_BY(ofproto_mutex);
> +    struct rconn_packet_counter *monitor_counter 
> OVS_GUARDED_BY(ofproto_mutex);
> +
> +    /* State of monitors for a single ongoing flow_mod.
> +     *
> +     * 'updates' is a list of "struct ofpbuf"s that contain
> +     * NXST_FLOW_MONITOR_REPLY messages representing the changes made by the
> +     * current flow_mod.
> +     *
> +     * When 'updates' is nonempty, 'sent_abbrev_update' is true if 'updates'
> +     * contains an update event of type NXFME_ABBREV and false otherwise.. */
> +    struct list updates OVS_GUARDED_BY(ofproto_mutex);
> +    bool sent_abbrev_update OVS_GUARDED_BY(ofproto_mutex);
>  };
>
>  static struct ofconn *ofconn_create(struct connmgr *, struct rconn *,
> @@ -1807,6 +1832,7 @@ COVERAGE_DEFINE(ofmonitor_resume);
>  enum ofperr
>  ofmonitor_create(const struct ofputil_flow_monitor_request *request,
>                   struct ofconn *ofconn, struct ofmonitor **monitorp)
> +    OVS_REQUIRES(ofproto_mutex)
>  {
>      struct ofmonitor *m;
>
> @@ -1832,6 +1858,7 @@ ofmonitor_create(const struct 
> ofputil_flow_monitor_request *request,
>
>  struct ofmonitor *
>  ofmonitor_lookup(struct ofconn *ofconn, uint32_t id)
> +    OVS_REQUIRES(ofproto_mutex)
>  {
>      struct ofmonitor *m;
>
> @@ -1846,6 +1873,7 @@ ofmonitor_lookup(struct ofconn *ofconn, uint32_t id)
>
>  void
>  ofmonitor_destroy(struct ofmonitor *m)
> +    OVS_REQUIRES(ofproto_mutex)
>  {
>      if (m) {
>          minimatch_destroy(&m->match);
> @@ -1952,6 +1980,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
>
>  void
>  ofmonitor_flush(struct connmgr *mgr)
> +    OVS_REQUIRES(ofproto_mutex)
>  {
>      struct ofconn *ofconn;
>
> @@ -1979,6 +2008,7 @@ ofmonitor_flush(struct connmgr *mgr)
>
>  static void
>  ofmonitor_resume(struct ofconn *ofconn)
> +    OVS_REQUIRES(ofproto_mutex)
>  {
>      struct rule_collection rules;
>      struct ofpbuf *resumed;
> @@ -2001,18 +2031,27 @@ ofmonitor_resume(struct ofconn *ofconn)
>      ofconn->monitor_paused = 0;
>  }
>
> +static bool
> +ofmonitor_may_resume(const struct ofconn *ofconn)
> +    OVS_REQUIRES(ofproto_mutex)
> +{
> +    return (ofconn->monitor_paused != 0
> +            && !rconn_packet_counter_n_packets(ofconn->monitor_counter));
> +}
> +
>  static void
>  ofmonitor_run(struct connmgr *mgr)
>  {
>      struct ofconn *ofconn;
>
> +    ovs_mutex_lock(&ofproto_mutex);
>      LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
> -        if (ofconn->monitor_paused
> -            && !rconn_packet_counter_n_packets(ofconn->monitor_counter)) {
> +        if (ofmonitor_may_resume(ofconn)) {
>              COVERAGE_INC(ofmonitor_resume);
>              ofmonitor_resume(ofconn);
>          }
>      }
> +    ovs_mutex_unlock(&ofproto_mutex);
>  }
>
>  static void
> @@ -2020,10 +2059,11 @@ ofmonitor_wait(struct connmgr *mgr)
>  {
>      struct ofconn *ofconn;
>
> +    ovs_mutex_lock(&ofproto_mutex);
>      LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
> -        if (ofconn->monitor_paused
> -            && !rconn_packet_counter_n_packets(ofconn->monitor_counter)) {
> +        if (ofmonitor_may_resume(ofconn)) {
>              poll_immediate_wake();
>          }
>      }
> +    ovs_mutex_unlock(&ofproto_mutex);
>  }
> diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
> index 55d08a6..505a757 100644
> --- a/ofproto/connmgr.h
> +++ b/ofproto/connmgr.h
> @@ -181,21 +181,26 @@ struct ofmonitor {
>  struct ofputil_flow_monitor_request;
>
>  enum ofperr ofmonitor_create(const struct ofputil_flow_monitor_request *,
> -                             struct ofconn *, struct ofmonitor **);
> -struct ofmonitor *ofmonitor_lookup(struct ofconn *, uint32_t id);
> -void ofmonitor_destroy(struct ofmonitor *);
> +                             struct ofconn *, struct ofmonitor **)
> +    OVS_REQUIRES(ofproto_mutex);
> +struct ofmonitor *ofmonitor_lookup(struct ofconn *, uint32_t id)
> +    OVS_REQUIRES(ofproto_mutex);
> +void ofmonitor_destroy(struct ofmonitor *)
> +    OVS_REQUIRES(ofproto_mutex);
>
>  void ofmonitor_report(struct connmgr *, struct rule *,
>                        enum nx_flow_update_event, enum 
> ofp_flow_removed_reason,
>                        const struct ofconn *abbrev_ofconn, ovs_be32 
> abbrev_xid)
>      OVS_REQUIRES(ofproto_mutex);
> -void ofmonitor_flush(struct connmgr *);
> +void ofmonitor_flush(struct connmgr *) OVS_REQUIRES(ofproto_mutex);
>
>
>  struct rule_collection;
>  void ofmonitor_collect_resume_rules(struct ofmonitor *, uint64_t seqno,
> -                                    struct rule_collection *);
> +                                    struct rule_collection *)
> +    OVS_REQUIRES(ofproto_mutex);
>  void ofmonitor_compose_refresh_updates(struct rule_collection *rules,
> -                                       struct list *msgs);
> +                                       struct list *msgs)
> +    OVS_REQUIRES(ofproto_mutex);
>
>  #endif /* connmgr.h */
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index 8e4f300..b1c93fb 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -4862,12 +4862,12 @@ handle_flow_monitor_request(struct ofconn *ofconn, 
> const struct ofp_header *oh)
>      return 0;
>
>  error:
> -    ovs_mutex_unlock(&ofproto_mutex);
> -
>      for (i = 0; i < n_monitors; i++) {
>          ofmonitor_destroy(monitors[i]);
>      }
>      free(monitors);
> +    ovs_mutex_unlock(&ofproto_mutex);
> +
>      return error;
>  }
>
> --
> 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