From ce27cbee00fa713c419d5fd5f7dece469f41c0a7 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 7 Oct 2011 15:43:43 -0700 Subject: [PATCH] cfm: Send properly formatted CCMs. Wireshark complained that Open vSwitch-generated CFM messages were malformed. Upon looking at the standard, I spotted that Open vSwitch failed to include the final, required "End TLV" byte with value 0. This commit adds the End TLV byte to generated CCMs but still accepts the truncated messages for backward compatibility. --- lib/cfm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/cfm.c b/lib/cfm.c index 3f3dcd2e..bdd3839c 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -49,8 +49,13 @@ static const uint8_t eth_addr_ccm_x[6] = { /* A 'ccm' represents a Continuity Check Message from the 802.1ag * specification. Continuity Check Messages are broadcast periodically so that - * hosts can determine whom they have connectivity to. */ -#define CCM_LEN 74 + * hosts can determine whom they have connectivity to. + * + * The minimum length of a CCM as specified by IEEE 802.1ag is 75 bytes. + * Previous versions of Open vSwitch generated 74-byte CCM messages, so we + * accept such messages too. */ +#define CCM_LEN 75 +#define CCM_ACCEPT_LEN 74 #define CCM_MAID_LEN 48 #define CCM_OPCODE 1 /* CFM message opcode meaning CCM. */ #define CCM_RDI_MASK 0x80 @@ -67,6 +72,9 @@ struct ccm { ovs_be16 interval_ms_x; /* Transmission interval in ms. */ ovs_be64 mpid64; /* MPID in extended mode. */ uint8_t zero[6]; + + /* TLV space. */ + uint8_t end_tlv; } __attribute__((packed)); BUILD_ASSERT_DECL(CCM_LEN == sizeof(struct ccm)); @@ -336,6 +344,7 @@ cfm_compose_ccm(struct cfm *cfm, struct ofpbuf *packet, ccm->flags = cfm->ccm_interval; memcpy(ccm->maid, cfm->maid, sizeof ccm->maid); memset(ccm->zero, 0, sizeof ccm->zero); + ccm->end_tlv = 0; if (cfm->extended) { ccm->mpid = htons(hash_mpid(cfm->mpid)); @@ -412,7 +421,7 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) struct eth_header *eth; eth = p->l2; - ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_LEN); + ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_ACCEPT_LEN); if (!ccm) { VLOG_INFO_RL(&rl, "%s: Received an unparseable 802.1ag CCM heartbeat.", -- 2.30.2