[ovs-dev] [PATCH] cfm: Prevent interval fault when demand mode is enabled on one end.

Alex Wang alexw at nicira.com
Thu Sep 19 18:39:15 UTC 2013


This commit prevents cfm from raising 'interval' fault when demand
mode is only enabled on one end of link.

Signed-off-by: Alex Wang <alexw at nicira.com>
---
 lib/cfm.c            |   18 +++++++++-------
 tests/automake.mk    |    1 +
 tests/cfm.at         |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/testsuite.at   |    1 +
 vswitchd/vswitch.xml |    5 +++--
 5 files changed, 73 insertions(+), 9 deletions(-)
 create mode 100644 tests/cfm.at

diff --git a/lib/cfm.c b/lib/cfm.c
index 4a46c05..03dd92d 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -105,6 +105,8 @@ struct cfm {
     uint32_t seq;          /* The sequence number of our last CCM. */
     uint8_t ccm_interval;  /* The CCM transmission interval. */
     int ccm_interval_ms;   /* 'ccm_interval' in milliseconds. */
+    int ccm_interval_fault_ms;/* Used to compute the fault interval, */
+                              /* in milliseconds. */
     uint16_t ccm_vlan;     /* Vlan tag of CCM PDUs.  CFM_RANDOM_VLAN if
                               random. */
     uint8_t ccm_pcp;       /* Priority of CCM PDUs. */
@@ -255,9 +257,8 @@ cfm_fault_interval(struct cfm *cfm) OVS_REQUIRES(mutex)
      * as a fault (likely due to a configuration error).  Thus we can check all
      * MPs at once making this quite a bit simpler.
      *
-     * According to the specification we should check when (ccm_interval_ms *
-     * 3.5)ms have passed. */
-    return (cfm->ccm_interval_ms * 7) / 2;
+     * We should check when (ccm_interval_fault_ms * 3.5)ms have passed. */
+    return (cfm->ccm_interval_fault_ms * 7) / 2;
 }
 
 static uint8_t
@@ -589,6 +590,7 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
 {
     uint8_t interval;
     int interval_ms;
+    int interval_fault_ms;
 
     if (!cfm_is_valid_mpid(s->extended, s->mpid) || s->interval <= 0) {
         return false;
@@ -598,7 +600,7 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
     cfm->mpid = s->mpid;
     cfm->opup = s->opup;
     interval = ms_to_ccm_interval(s->interval);
-    interval_ms = ccm_interval_to_ms(interval);
+    interval_fault_ms = interval_ms = ccm_interval_to_ms(interval);
 
     atomic_store(&cfm->check_tnl_key, s->check_tnl_key);
     atomic_store(&cfm->extended, s->extended);
@@ -607,11 +609,11 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
     cfm->ccm_pcp = s->ccm_pcp & (VLAN_PCP_MASK >> VLAN_PCP_SHIFT);
     if (s->extended && interval_ms != s->interval) {
         interval = 0;
-        interval_ms = MIN(s->interval, UINT16_MAX);
+        interval_fault_ms = interval_ms = MIN(s->interval, UINT16_MAX);
     }
 
     if (s->extended && s->demand) {
-        interval_ms = MAX(interval_ms, 500);
+        interval_fault_ms = MAX(interval_ms, 500);
         if (!cfm->demand) {
             cfm->demand = true;
             cfm->rx_packets = cfm_rx_packets(cfm);
@@ -620,9 +622,11 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
         cfm->demand = false;
     }
 
-    if (interval != cfm->ccm_interval || interval_ms != cfm->ccm_interval_ms) {
+    if (interval != cfm->ccm_interval || interval_ms != cfm->ccm_interval_ms
+        || interval_fault_ms != cfm->ccm_interval_fault_ms) {
         cfm->ccm_interval = interval;
         cfm->ccm_interval_ms = interval_ms;
+        cfm->ccm_interval_fault_ms = interval_fault_ms;
 
         timer_set_expired(&cfm->tx_timer);
         timer_set_duration(&cfm->fault_timer, cfm_fault_interval(cfm));
diff --git a/tests/automake.mk b/tests/automake.mk
index 60d3640..8f51a65 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -22,6 +22,7 @@ TESTSUITE_AT = \
 	tests/odp.at \
 	tests/multipath.at \
 	tests/bfd.at \
+	tests/cfm.at \
 	tests/lacp.at \
 	tests/learn.at \
 	tests/vconn.at \
diff --git a/tests/cfm.at b/tests/cfm.at
new file mode 100644
index 0000000..638e03f
--- /dev/null
+++ b/tests/cfm.at
@@ -0,0 +1,57 @@
+AT_BANNER([cfm])
+
+m4_define([CFM_CHECK_EXTENDED], [
+AT_CHECK([ovs-appctl cfm/show $1 | sed -e '/next CCM tx:/d' | sed -e '/next fault check:/d' | sed -e  '/recv since check:/d'],[0],
+[dnl
+---- $1 ----
+MPID $2: extended
+	average health: $3
+	opstate: $4
+	remote_opstate: $5
+	interval: $6
+Remote MPID $7
+	opstate: $8
+])
+])
+
+# test cfm under demand mode.
+AT_SETUP([cfm - demand mode])
+#Create 2 bridges connected by patch ports and enable BFD
+OVS_VSWITCHD_START([add-br br1 -- \
+                    set bridge br1 datapath-type=dummy \
+                    other-config:hwaddr=aa:55:aa:56:00:00 -- \
+                    add-port br1 p1 -- set Interface p1 type=patch \
+                    options:peer=p0 -- \
+                    add-port br0 p0 -- set Interface p0 type=patch \
+                    options:peer=p1 -- \
+                    set Interface p0 cfm_mpid=1 other_config:cfm_interval=300 other_config:cfm_extended=true -- \
+                    set Interface p1 cfm_mpid=2 other_config:cfm_interval=300 other_config:cfm_extended=true ])
+
+ovs-appctl time/stop
+# wait for a while to stablize cfm.
+for i in `seq 0 100`; do ovs-appctl time/warp 100; done
+CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
+CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
+
+# turn on demand mode on one end.
+AT_CHECK([ovs-vsctl set interface p0 other_config:cfm_demand=true])
+
+# cfm should never go down.
+for i in `seq 0 100`
+do
+    ovs-appctl time/warp 100
+    CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
+    CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
+done
+
+# turn on demand mode on the other end.
+AT_CHECK([ovs-vsctl set interface p1 other_config:cfm_demand=true])
+for i in `seq 0 100`
+do
+    ovs-appctl time/warp 100
+    CFM_CHECK_EXTENDED([p0], [1], [100], [up], [up], [300ms], [2], [up])
+    CFM_CHECK_EXTENDED([p1], [2], [100], [up], [up], [300ms], [1], [up])
+done
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 43efc09..9e16f94 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -68,6 +68,7 @@ m4_include([tests/ovsdb-macros.at])
 m4_include([tests/ofproto-macros.at])
 
 m4_include([tests/bfd.at])
+m4_include([tests/cfm.at])
 m4_include([tests/lacp.at])
 m4_include([tests/library.at])
 m4_include([tests/heap.at])
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 4b42ec7..5fd5b3b 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2142,8 +2142,9 @@
           <ul>
             <li>
               To ensure that ovs-vswitchd has enough time to pull statistics
-              from the datapath, the minimum
-              <ref column="other_config" key="cfm_interval"/> is 500ms.
+              from the datapath, the fault detection interval is set to
+              3.5 * MAX(<ref column="other_config" key="cfm_interval"/>, 500)
+              ms.
             </li>
 
             <li>
-- 
1.7.9.5




More information about the dev mailing list