[ovs-dev] [cfm_v2 7/9] cfm: Allow accurate transmission intervals in extended mode.

Ethan Jackson ethan at nicira.com
Fri Sep 9 01:59:51 UTC 2011


The standard CFM protocol only allows a handful of transmission
rates.  This is particularly problematic if you want to support a
transmission rate slower than 100 ms and faster than 1000 ms.

This patch allows arbitrary transmission rates (between 1 ms and
65535 ms).  It does this by commandeering parts of a reserved
"zero" field in the ccm message.  This breaks wire compatibility
with standard 802.1ag implementations, and thus is only supported
in extended mode.

Bug #7014.
---
 lib/cfm.c            |   41 +++++++++++++++++++++++++++++++----------
 vswitchd/vswitch.xml |    5 ++++-
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/lib/cfm.c b/lib/cfm.c
index d526a05..94079b6 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -61,7 +61,10 @@ struct ccm {
     ovs_be32 seq;
     ovs_be16 mpid;
     uint8_t  maid[CCM_MAID_LEN];
-    uint8_t  zero[16]; /* Defined by ITU-T Y.1731 should be zero */
+
+    /* Defined by ITU-T Y.1731 should be zero */
+    ovs_be16 interval_ms_x;      /* Transmission interval in ms. */
+    uint8_t  zero[14];
 } __attribute__((packed));
 BUILD_ASSERT_DECL(CCM_LEN == sizeof(struct ccm));
 
@@ -312,6 +315,11 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet,
     memcpy(ccm->maid, cfm->maid, sizeof ccm->maid);
     memset(ccm->zero, 0, sizeof ccm->zero);
 
+    if (cfm->ccm_interval == 0) {
+        assert(cfm->extended);
+        ccm->interval_ms_x = htons(cfm->ccm_interval_ms);
+    }
+
     if (hmap_is_empty(&cfm->remote_mps)) {
         ccm->flags |= CCM_RDI_MASK;
     }
@@ -330,6 +338,7 @@ bool
 cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
 {
     uint8_t interval;
+    int interval_ms;
 
     if (!cfm_is_valid_mpid(s->mpid) || s->interval <= 0) {
         return false;
@@ -338,10 +347,16 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s)
     cfm->mpid = s->mpid;
     cfm->extended = s->extended;
     interval = ms_to_ccm_interval(s->interval);
+    interval_ms = ccm_interval_to_ms(interval);
+
+    if (cfm->extended && interval_ms != s->interval) {
+        interval = 0;
+        interval_ms = MIN(s->interval, UINT16_MAX);
+    }
 
-    if (interval != cfm->ccm_interval) {
+    if (interval != cfm->ccm_interval || interval_ms != cfm->ccm_interval_ms) {
         cfm->ccm_interval = interval;
-        cfm->ccm_interval_ms = ccm_interval_to_ms(interval);
+        cfm->ccm_interval_ms = interval_ms;
 
         timer_set_expired(&cfm->tx_timer);
         timer_set_duration(&cfm->fault_timer, cfm_fault_interval(cfm));
@@ -367,10 +382,6 @@ void
 cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
 {
     struct ccm *ccm;
-    bool ccm_rdi;
-    uint16_t ccm_mpid;
-    uint8_t ccm_interval;
-    struct remote_mp *rmp;
     struct eth_header *eth;
 
     eth = p->l2;
@@ -402,9 +413,12 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
         VLOG_WARN_RL(&rl, "%s: Received unexpected remote MAID from MAC "
                      ETH_ADDR_FMT, cfm->name, ETH_ADDR_ARGS(eth->eth_src));
     } else {
-        ccm_mpid = ntohs(ccm->mpid);
-        ccm_interval = ccm->flags & 0x7;
-        ccm_rdi = ccm->flags & CCM_RDI_MASK;
+        uint16_t ccm_mpid = ntohs(ccm->mpid);
+        uint8_t ccm_interval = ccm->flags & 0x7;
+        bool ccm_rdi = ccm->flags & CCM_RDI_MASK;
+        uint16_t ccm_interval_ms_x = ntohs(ccm->interval_ms_x);
+
+        struct remote_mp *rmp;
 
         if (ccm_interval != cfm->ccm_interval) {
             VLOG_WARN_RL(&rl, "%s: received a CCM with an invalid interval"
@@ -412,6 +426,13 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p)
                          ccm_interval, ccm_mpid);
         }
 
+        if (cfm->extended && ccm_interval == 0
+            && ccm_interval_ms_x != cfm->ccm_interval_ms) {
+            VLOG_WARN_RL(&rl, "%s: received a CCM with an invalid extended"
+                         " interval (%"PRIu16"ms) from RMP %"PRIu16, cfm->name,
+                         ccm_interval_ms_x, ccm_mpid);
+        }
+
         rmp = lookup_remote_mp(cfm, ccm_mpid);
         if (rmp) {
             rmp->recv = true;
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index e3953b4..eebf8e4 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -1418,7 +1418,10 @@
           <dd> When true, the CFM module operates in extended mode. This causes
             it to use a nonstandard destination address to avoid conflicting
             with compliant implementations which may be running concurrently on
-            the network. Defaults to false. </dd>
+            the network. Furthermore, extended mode increases the accuracy of
+            the <code>cfm_interval</code> configuration parameter by breaking
+            wire compatibility with 802.1ag compliant implementations.
+            Defaults to false.</dd>
           <dt><code>bond-stable-id</code></dt>
           <dd> A positive integer using in <code>stable</code> bond mode to
             make slave selection decisions.  Allocating
-- 
1.7.6.1




More information about the dev mailing list