From de72402954abc382e63532e6d179583c5eea6227 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Tue, 30 Aug 2011 17:37:15 -0700 Subject: [PATCH] cfm: Allow accurate transmission intervals in extended mode. 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 b4f64c71..cb5df8cc 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)); @@ -318,6 +321,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; } @@ -336,6 +344,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; @@ -344,10 +353,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)); @@ -371,10 +386,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; @@ -406,9 +417,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" @@ -416,6 +430,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 5151fea2..daac9e1d 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1429,7 +1429,10 @@
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.
+ the network. Furthermore, extended mode increases the accuracy of + the cfm_interval configuration parameter by breaking + wire compatibility with 802.1ag compliant implementations. + Defaults to false.
bond-stable-id
A positive integer using in stable bond mode to make slave selection decisions. Allocating -- 2.30.2