cfm: Extracts the cfm status in one function.
authorAlex Wang <alexw@nicira.com>
Tue, 10 Jun 2014 01:35:35 +0000 (18:35 -0700)
committerAlex Wang <alexw@nicira.com>
Sat, 14 Jun 2014 00:47:32 +0000 (17:47 -0700)
This commit adds a new function, cfm_get_status(), for extracting
all cfm status at once.  This helps avoid the sequence of lock
acquire/release in current implementation of status query.

Signed-off-by: Alex Wang <alexw@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/cfm.c
lib/cfm.h
ofproto/ofproto-dpif.c
ofproto/ofproto-provider.h
ofproto/ofproto.c
ofproto/ofproto.h
vswitchd/bridge.c

index c271e1e..447a095 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -925,26 +925,42 @@ cfm_get_health(const struct cfm *cfm) OVS_EXCLUDED(mutex)
     return health;
 }
 
+static int
+cfm_get_opup__(const struct cfm *cfm_) OVS_REQUIRES(mutex)
+{
+    struct cfm *cfm = CONST_CAST(struct cfm *, cfm_);
+    bool extended;
+
+    atomic_read(&cfm->extended, &extended);
+
+    return extended ? cfm->remote_opup : -1;
+}
+
 /* Gets the operational state of 'cfm'.  'cfm' is considered operationally down
  * if it has received a CCM with the operationally down bit set from any of its
  * remote maintenance points. Returns 1 if 'cfm' is operationally up, 0 if
  * 'cfm' is operationally down, or -1 if 'cfm' has no operational state
  * (because it isn't in extended mode). */
 int
-cfm_get_opup(const struct cfm *cfm_) OVS_EXCLUDED(mutex)
+cfm_get_opup(const struct cfm *cfm) OVS_EXCLUDED(mutex)
 {
-    struct cfm *cfm = CONST_CAST(struct cfm *, cfm_);
-    bool extended;
     int opup;
 
     ovs_mutex_lock(&mutex);
-    atomic_read(&cfm->extended, &extended);
-    opup = extended ? cfm->remote_opup : -1;
+    opup = cfm_get_opup__(cfm);
     ovs_mutex_unlock(&mutex);
 
     return opup;
 }
 
+static void
+cfm_get_remote_mpids__(const struct cfm *cfm, uint64_t **rmps, size_t *n_rmps)
+    OVS_REQUIRES(mutex)
+{
+    *rmps = xmemdup(cfm->rmps_array, cfm->rmps_array_len * sizeof **rmps);
+    *n_rmps = cfm->rmps_array_len;
+}
+
 /* Populates 'rmps' with an array of remote maintenance points reachable by
  * 'cfm'. The number of remote maintenance points is written to 'n_rmps'.
  * 'cfm' retains ownership of the array written to 'rmps' */
@@ -953,8 +969,20 @@ cfm_get_remote_mpids(const struct cfm *cfm, uint64_t **rmps, size_t *n_rmps)
     OVS_EXCLUDED(mutex)
 {
     ovs_mutex_lock(&mutex);
-    *rmps = xmemdup(cfm->rmps_array, cfm->rmps_array_len * sizeof **rmps);
-    *n_rmps = cfm->rmps_array_len;
+    cfm_get_remote_mpids__(cfm, rmps, n_rmps);
+    ovs_mutex_unlock(&mutex);
+}
+
+/* Extracts the status of 'cfm' and fills in the 's'. */
+void
+cfm_get_status(const struct cfm *cfm, struct cfm_status *s) OVS_EXCLUDED(mutex)
+{
+    ovs_mutex_lock(&mutex);
+    s->faults = cfm_get_fault__(cfm);
+    s->remote_opstate = cfm_get_opup__(cfm);
+    s->flap_count = cfm->flap_count;
+    s->health = cfm->health;
+    cfm_get_remote_mpids__(cfm, &s->rmps, &s->n_rmps);
     ovs_mutex_unlock(&mutex);
 }
 
index 13fdc60..a5d4cdf 100644 (file)
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -63,6 +63,29 @@ struct cfm_settings {
     bool check_tnl_key;         /* Verify inbound packet key? */
 };
 
+/* CFM status query. */
+struct cfm_status {
+    /* 0 if not faulted, otherwise a combination of one or more reasons. */
+    enum cfm_fault_reason faults;
+
+    /* 0 if the remote CFM endpoint is operationally down,
+     * 1 if the remote CFM endpoint is operationally up,
+     * -1 if we don't know because the remote CFM endpoint is not in extended
+     * mode. */
+    int remote_opstate;
+
+    uint64_t flap_count;
+
+    /* Ordinarily a "health status" in the range 0...100 inclusive, with 0
+     * being worst and 100 being best, or -1 if the health status is not
+     * well-defined. */
+    int health;
+
+    /* MPIDs of remote maintenance points whose CCMs have been received. */
+    uint64_t *rmps;
+    size_t n_rmps;
+};
+
 void cfm_init(void);
 struct cfm *cfm_create(const struct netdev *);
 struct cfm *cfm_ref(const struct cfm *);
@@ -82,6 +105,7 @@ uint64_t cfm_get_flap_count(const struct cfm *);
 int cfm_get_health(const struct cfm *);
 int cfm_get_opup(const struct cfm *);
 void cfm_get_remote_mpids(const struct cfm *, uint64_t **rmps, size_t *n_rmps);
+void cfm_get_status(const struct cfm *, struct cfm_status *);
 const char *cfm_fault_reason_to_str(int fault);
 
 long long int cfm_wake_time(struct cfm*);
index e6d88bc..9aa1255 100644 (file)
@@ -1811,18 +1811,14 @@ out:
 
 static int
 get_cfm_status(const struct ofport *ofport_,
-               struct ofproto_cfm_status *status)
+               struct cfm_status *status)
 {
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
     int ret = 0;
 
     if (ofport->cfm) {
         if (cfm_check_status_change(ofport->cfm)) {
-            status->faults = cfm_get_fault(ofport->cfm);
-            status->flap_count = cfm_get_flap_count(ofport->cfm);
-            status->remote_opstate = cfm_get_opup(ofport->cfm);
-            status->health = cfm_get_health(ofport->cfm);
-            cfm_get_remote_mpids(ofport->cfm, &status->rmps, &status->n_rmps);
+            cfm_get_status(ofport->cfm, status);
         } else {
             ret = NO_STATUS_CHANGE;
         }
index c8d70e6..6e8cd9b 100644 (file)
@@ -1360,7 +1360,7 @@ struct ofproto_class {
      * returned in 'status->rmps'.  '*status' is indeterminate if the return
      * value is non-zero. */
     int (*get_cfm_status)(const struct ofport *ofport,
-                          struct ofproto_cfm_status *status);
+                          struct cfm_status *status);
 
     /* Configures BFD on 'ofport'.
      *
index a05a444..fb9313b 100644 (file)
@@ -3692,7 +3692,7 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto,
  * '*status' is indeterminate if the return value is non-zero. */
 int
 ofproto_port_get_cfm_status(const struct ofproto *ofproto, ofp_port_t ofp_port,
-                            struct ofproto_cfm_status *status)
+                            struct cfm_status *status)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     return (ofport && ofproto->ofproto_class->get_cfm_status
index de078b7..5f5e6c8 100644 (file)
@@ -399,32 +399,9 @@ void ofproto_get_netflow_ids(const struct ofproto *,
 void ofproto_get_ofproto_controller_info(const struct ofproto *, struct shash *);
 void ofproto_free_ofproto_controller_info(struct shash *);
 
-/* CFM status query. */
-struct ofproto_cfm_status {
-    /* 0 if not faulted, otherwise a combination of one or more reasons. */
-    enum cfm_fault_reason faults;
-
-    /* 0 if the remote CFM endpoint is operationally down,
-     * 1 if the remote CFM endpoint is operationally up,
-     * -1 if we don't know because the remote CFM endpoint is not in extended
-     * mode. */
-    int remote_opstate;
-
-    uint64_t flap_count;
-
-    /* Ordinarily a "health status" in the range 0...100 inclusive, with 0
-     * being worst and 100 being best, or -1 if the health status is not
-     * well-defined. */
-    int health;
-
-    /* MPIDs of remote maintenance points whose CCMs have been received. */
-    uint64_t *rmps;
-    size_t n_rmps;
-};
-
 int ofproto_port_get_cfm_status(const struct ofproto *,
                                 ofp_port_t ofp_port,
-                                struct ofproto_cfm_status *);
+                                struct cfm_status *);
 \f
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
  *
index 9764c1f..014ef6f 100644 (file)
@@ -1926,7 +1926,7 @@ static void
 iface_refresh_cfm_stats(struct iface *iface)
 {
     const struct ovsrec_interface *cfg = iface->cfg;
-    struct ofproto_cfm_status status;
+    struct cfm_status status;
     int error;
 
     error = ofproto_port_get_cfm_status(iface->port->bridge->ofproto,