Merge branch 'mainstream'
[sliver-openvswitch.git] / lib / cfm.c
index 0277fe6..297894e 100644 (file)
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -156,7 +156,7 @@ static unixctl_cb_func cfm_unixctl_show;
 static unixctl_cb_func cfm_unixctl_set_fault;
 
 static uint64_t
-cfm_rx_packets(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex)
+cfm_rx_packets(const struct cfm *cfm) OVS_REQUIRES(mutex)
 {
     struct netdev_stats stats;
 
@@ -168,7 +168,7 @@ cfm_rx_packets(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex)
 }
 
 static const uint8_t *
-cfm_ccm_addr(const struct cfm *cfm)
+cfm_ccm_addr(struct cfm *cfm)
 {
     bool extended;
     atomic_read(&cfm->extended, &extended);
@@ -204,7 +204,7 @@ ds_put_cfm_fault(struct ds *ds, int fault)
 }
 
 static void
-cfm_generate_maid(struct cfm *cfm) OVS_REQ_WRLOCK(mutex)
+cfm_generate_maid(struct cfm *cfm) OVS_REQUIRES(mutex)
 {
     const char *ovs_md_name = "ovs";
     const char *ovs_ma_name = "ovs";
@@ -247,7 +247,7 @@ ccm_interval_to_ms(uint8_t interval)
 }
 
 static long long int
-cfm_fault_interval(struct cfm *cfm) OVS_REQ_WRLOCK(mutex)
+cfm_fault_interval(struct cfm *cfm) OVS_REQUIRES(mutex)
 {
     /* According to the 802.1ag specification we should assume every other MP
      * with the same MAID has the same transmission interval that we have.  If
@@ -289,7 +289,7 @@ cfm_is_valid_mpid(bool extended, uint64_t mpid)
 }
 
 static struct remote_mp *
-lookup_remote_mp(const struct cfm *cfm, uint64_t mpid) OVS_REQ_WRLOCK(mutex)
+lookup_remote_mp(const struct cfm *cfm, uint64_t mpid) OVS_REQUIRES(mutex)
 {
     struct remote_mp *rmp;
 
@@ -390,6 +390,8 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex)
         struct remote_mp *rmp, *rmp_next;
         bool old_cfm_fault = cfm->fault;
         bool demand_override;
+        bool rmp_set_opup = false;
+        bool rmp_set_opdown = false;
 
         cfm->fault = cfm->recv_fault;
         cfm->recv_fault = 0;
@@ -399,7 +401,6 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex)
         cfm->rmps_array = xmalloc(hmap_count(&cfm->remote_mps) *
                                   sizeof *cfm->rmps_array);
 
-        cfm->remote_opup = true;
         if (cfm->health_interval == CFM_HEALTH_INTERVAL) {
             /* Calculate the cfm health of the interface.  If the number of
              * remote_mpids of a cfm interface is > 1, the cfm health is
@@ -451,14 +452,23 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex)
             } else {
                 rmp->recv = false;
 
-                if (!rmp->opup) {
-                    cfm->remote_opup = rmp->opup;
+                if (rmp->opup) {
+                    rmp_set_opup = true;
+                } else {
+                    rmp_set_opdown = true;
                 }
 
                 cfm->rmps_array[cfm->rmps_array_len++] = rmp->mpid;
             }
         }
 
+        if (rmp_set_opdown) {
+            cfm->remote_opup = false;
+        }
+        else if (rmp_set_opup) {
+            cfm->remote_opup = true;
+        }
+
         if (hmap_is_empty(&cfm->remote_mps)) {
             cfm->fault |= CFM_FAULT_RECV;
         }
@@ -638,9 +648,10 @@ cfm_set_netdev(struct cfm *cfm, const struct netdev *netdev)
 /* Returns true if 'cfm' should process packets from 'flow'.  Sets
  * fields in 'wc' that were used to make the determination. */
 bool
-cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow,
+cfm_should_process_flow(const struct cfm *cfm_, const struct flow *flow,
                         struct flow_wildcards *wc)
 {
+    struct cfm *cfm = CONST_CAST(struct cfm *, cfm_);
     bool check_tnl_key;
 
     atomic_read(&cfm->check_tnl_key, &check_tnl_key);
@@ -785,7 +796,7 @@ out:
 }
 
 static int
-cfm_get_fault__(const struct cfm *cfm) OVS_REQ_WRLOCK(mutex)
+cfm_get_fault__(const struct cfm *cfm) OVS_REQUIRES(mutex)
 {
     if (cfm->fault_override >= 0) {
         return cfm->fault_override ? CFM_FAULT_OVERRIDE : 0;
@@ -829,8 +840,9 @@ cfm_get_health(const struct cfm *cfm) OVS_EXCLUDED(mutex)
  * '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;
 
@@ -856,7 +868,7 @@ cfm_get_remote_mpids(const struct cfm *cfm, uint64_t **rmps, size_t *n_rmps)
 }
 
 static struct cfm *
-cfm_find(const char *name) OVS_REQ_WRLOCK(&mutex)
+cfm_find(const char *name) OVS_REQUIRES(mutex)
 {
     struct cfm *cfm;
 
@@ -869,7 +881,7 @@ cfm_find(const char *name) OVS_REQ_WRLOCK(&mutex)
 }
 
 static void
-cfm_print_details(struct ds *ds, const struct cfm *cfm) OVS_REQ_WRLOCK(&mutex)
+cfm_print_details(struct ds *ds, struct cfm *cfm) OVS_REQUIRES(mutex)
 {
     struct remote_mp *rmp;
     bool extended;
@@ -916,7 +928,7 @@ cfm_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[],
                  void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
-    const struct cfm *cfm;
+    struct cfm *cfm;
 
     ovs_mutex_lock(&mutex);
     if (argc > 1) {